P1600 天天爱跑步
Posted lovedsr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1600 天天爱跑步相关的知识,希望对你有一定的参考价值。
lca真心不太会,这里只介绍60分做法,100的太难辣简单了就不介绍了
n<=1000
zz回溯爆搜
S[i]全部相等
这dfs序都不用lca的,2333,差分,然后输出判断一下是否是0(1到i的时间是固定的)
退化成一条链子
一个点i的ans就是i-time[i]和i+tim[i]的起点个数(当然要合法啦)
乱搞就好了,这里写的nlogn的
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=300000;
const int maxn_25=1000;
struct edge {
int v,nxt;
}e[maxn<<1];
struct node {
int x,id;
bool operator < (const node b) const {
return x>b.x;
}
};
struct node1 {
int x,id;
bool operator < (const node1 b) const {
return x<b.x;
}
};
int head[maxn<<1],tot;
int tim[maxn],n,m,S[maxn],T[maxn],deep[maxn<<1];
int pd_25,ans_25[maxn_25]; //baoli 25 zhuanyong
int tot_a,a_c[maxn<<1],find_a[maxn],ans_c[maxn];//all s == 1 zhuanyong
int vis[maxn<<1],cf[maxn<<1],dsr[maxn<<1];
int ans[maxn];
void add_edge(int u,int v) {
e[++tot].v=v;
e[tot].nxt=head[u];
head[u]=tot;
}
inline int read() {
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9')
{if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9')
{x=(x<<3)+(x<<1)+s-'0',s=getchar();}
return x*f;
}
void dfs_25(int u,int f,int end,int cnt) {
if(u==end) {
if(cnt==tim[u]) ans_25[u]++;
pd_25=1;
return;
}
if(pd_25) return;
if(cnt==tim[u]) ans_25[u]++;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v==f) continue;
dfs_25(v,u,end,cnt+1);
if(pd_25) return;
}
if(cnt==tim[u]) ans_25[u]--;
}
void dfs_deep(int u,int f,int cnt) {
deep[u]=cnt;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(f==v) continue;
dfs_deep(v,u,cnt+1);
}
}
void dfs_xu(int u,int f) {
a_c[++tot_a]=0;
find_a[u]=tot_a;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v==f) continue;
dfs_xu(v,u);
}
a_c[++tot_a]=0;
vis[tot_a]=u;
dsr[u]=tot_a;
}
int main() {
n=read(),m=read();
for(int i=1;i<n;++i) {
int x=read(),y=read();
add_edge(x,y);
add_edge(y,x);
}
for(int i=1;i<=n;++i)
tim[i]=read();
for(int i=1;i<=m;++i)
S[i]=read(),T[i]=read();
//baoli_25
if(n<=1000) {
for(int i=1;i<=m;++i) {
pd_25=0;
dfs_25(S[i],0,T[i],0);
}
for(int j=1;j<=n;++j)
printf("%d ",ans_25[j]);
return 0;
}
int wakaka=1;
for(int i=1;i<=m;++i)
if(S[i]!=1) wakaka=0;
if(wakaka)
{
//all S[i]==1 fen==20
dfs_deep(1,0,0);//1 -> i deep
dfs_xu(1,0);
//chafen
for(int i=1;i<=m;++i) {
//1->i
cf[find_a[S[i]]]++;
cf[find_a[T[i]]+1]--;
}
//qiouhe
for(int i=1;i<=tot_a;++i) {
a_c[i]=a_c[i-1]+cf[i];
}
for(int i=1;i<=n;++i) {
if(deep[i]==tim[i])
printf("%d ",a_c[find_a[i]]-a_c[dsr[i]]);
else
printf("0 ");
}
return 0;
}
priority_queue<node> q;
for(int i=1;i<=m;++i)
{
if(S[i] > T[i]) continue;
dsr[S[i]]++;
node x;
x.x=T[i]+1;
x.id=S[i];
q.push(x);
}
for(int i=1;i<=n;++i)
{
while(!q.empty()&&q.top().x==i)
dsr[q.top().id]--,q.pop();
if(i-tim[i]>=1)
ans[i]+=dsr[i-tim[i]];
}
priority_queue< node1 > qq;
memset(dsr,0,sizeof(dsr));
for(int i=1;i<=m;++i)
{
if(S[i] <= T[i]) continue;
dsr[S[i]]++;
node1 x;
x.x=T[i]-1;
x.id=S[i];
qq.push(x);
}
for(int i=n;i>=1;--i)
{
while(!qq.empty()&&qq.top().x==i)
dsr[qq.top().id]--,qq.pop();
// puts("debug");
// for(int j=1;j<=n;++j)
// cout<<dsr[j]<<" ";puts("");
if(i+tim[i]<=n)
ans[i]+=dsr[i+tim[i]];
}
for(int i=1;i<=n;++i)
printf("%d ",ans[i]);
return 0;
}
以上是关于P1600 天天爱跑步的主要内容,如果未能解决你的问题,请参考以下文章