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;
}

原文地址:https://www.cnblogs.com/lovedsr/p/9681689.html

时间: 2024-08-07 11:22:39

P1600 天天爱跑步的相关文章

Luogu P1600 天天爱跑步 树上差分

Luogu P1600 天天爱跑步 ### 树上差分 题目链接 树上问题 没看出怎么差分 被观察到的条件有两个 lca前一半(包括lca) \(d[S_i]-d[x]=w[x]\) \(d[i]\)表示节点深度 lca后一半 \(d[S_i]+d[x]-2*d[lca(S_i,T_i)]=w[x]\) 但是具体怎么实现这个公式?? 实现 \(d[S_i]=w[x]+d[x]\) 可以转化为线段树合并模型 在\(S_i\)到\(lca\)的路径上增加\(d[S_i]\)的价值 最后求出各点的\(w

[luogu]P1600 天天爱跑步[LCA]

[luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含n个结点和n−1条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si?,终点为Ti? .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速

luogu P1600 天天爱跑步 |树上差分+LCA

题目描述 小c 同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nnn 个结点和 n?1n-1n?1 条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从 111 到 nnn 的连续正整数. 现在有 mmm 个玩家,第 iii 个玩家的起点为 sis_isi?,终点为 tit_iti?.每天打卡任务开始时,所有玩家在第 000 秒同时

【NOIP2016】天天爱跑步(树上差分)

题意: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两 个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到N的连续正整数.现在有个玩家,第个玩家的 起点为Si ,终点为Ti  .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该

天天爱跑步[NOIP2016]

时间限制:2 s   内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵包含n个结点和n-1条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si,终点为Ti.每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发,以每秒跑一条边的速度,不间断

bzoj4719[Noip2016]天天爱跑步

Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到N的连续正整数.现在有个玩家,第个玩家的起点为Si ,终点为Ti  .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度,不间断地沿着最短路径向着自己的终点跑去, 跑到

noip 2016 天天爱跑步

描述 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一棵包含n个结点和n - 1条边的树,每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到n的连续正整数. 现在有m个玩家,第i个玩家的起点为Si,终点为Ti.每天打卡任务开始时,所有玩家 在第0秒 同时从 自己的起点 出发,以 每秒跑一条边 的速度,不间断地沿着最短路径向着 自己的终点 跑去,

Noip 2016 天天爱跑步 【树上倍增+深搜】

题目: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 个结点和 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从到的连续正整数. 现在有个玩家,第个玩家的起点为 ,终点为 .每天打卡任务开始时,所有玩家在第秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务.

bzoj 4719: [Noip2016]天天爱跑步

Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务.这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两 个结点,且任意两个结点存在一条路径互相可达.树上结点编号为从1到N的连续正整数.现在有个玩家,第个玩家的 起点为Si ,终点为Ti  .每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去