zoukankan      html  css  js  c++  java
  • [NOIP2016]天天爱跑步

    [NOIP2016]天天爱跑步

    luogu
    BZOJ
    神仙题
    来看看部分分

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5;
    int re(){
        int x=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    int n,m,cnt;
    int last[N],w[N],t[1000],dep[N],val[N],t1[N],t2[N];
    vector<int>v1[N],v2[N];
    struct edge{int to,next;}e[N<<1];
    void link(int u,int v){
        e[++cnt]=(edge){v,last[u]};last[u]=cnt;
        e[++cnt]=(edge){u,last[v]};last[v]=cnt;
    }
    void solve1(){
        while(m--){t[re()]++;re();}
        for(int i=1;i<=n;i++){
            if(!w[i])printf("%d ",t[i]);
            else printf("0 ");
        }
    }
    void solve2(){
        while(m--){t[re()]++;re();}
        for(int i=1;i<=n;i++)printf("%d ",t[i]);
    }
    bool dfs(int u,int ed,int time,int fa){
        for(int i=last[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa)continue;
            if(dfs(v,ed,time+1,u)){
                t[u]+=(w[u]==time);
                return 1;
            }
        }
        if(u==ed)t[u]+=(w[u]==time);
        return u==ed;
    }
    void solve3(){
        while(m--){
            int st=re(),ed=re();
            dfs(st,ed,0,0);
        }
        for(int i=1;i<=n;i++)printf("%d ",t[i]);
    }
    void solve4(){
        while(m--){
            int st=re(),ed=re();
            if(st<=ed)t1[st]++,v1[ed].push_back(st);
            else t2[st]++,v2[ed].push_back(st);
        }
        for(int i=1;i<=n;i++){
            if(i>w[i])val[i]+=t1[i-w[i]];
            int sz=v1[i].size();
            for(int j=0;j<sz;j++)t1[v1[i][j]]--;
        }
        for(int i=n;i>=1;i--){
            if(i+w[i]<=n)val[i]+=t2[i+w[i]];
            int sz=v2[i].size();
            for(int j=0;j<sz;j++)t2[v2[i][j]]--;
        }
        for(int i=1;i<=n;i++)printf("%d ",val[i]);
    }
    void dfs(int u,int fa){
        for(int i=last[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa)continue;
            dep[v]=dep[u]+1;
            dfs(v,u);val[u]+=val[v];
        }
    }
    void solve5(){
        while(m--){re();val[re()]++;}
        dfs(1,0);
        for(int i=1;i<=n;i++)
            printf("%d ",w[i]==dep[i]?val[i]:0);
    }
    void dfs1(int u,int fa){
        t2[dep[u]]+=t1[u];int pre=t2[dep[u]+w[u]];
        for(int i=last[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa)continue;
            dfs1(v,u);
        }
        val[u]=t2[dep[u]+w[u]]-pre;
    }
    void solve6(){
        while(m--){t1[re()]++;re();}
        dfs(1,0);dfs1(1,0);
        for(int i=1;i<=n;i++)printf("%d ",val[i]);
    }
    int main(){
        n=re(),m=re();int Type=n%10;
        for(int i=1,u,v;i<n;i++){
            u=re(),v=re();link(u,v);
        }
        for(int i=1;i<=n;i++)w[i]=re();
        if(Type==1)solve1();
        if(Type==2)solve2();
        if(Type==3)solve3();
        if(Type==4)solve4();
        if(Type==5)solve5();
        if(Type==6)solve6();
        return 0;
    }
    

    部分分拼了6档,80分
    考noip就要像这样,难题一般有很多部分分,一档一档想,不要贪AC
    关键点就在一个链的部分分和一个(T_i=1)的部分分


    • 一个点的答案只有两个来源,(i-w_i)(i+w_i)
      但是从这两个点出发不一定走得到(i),也不一定往(i)
      考虑分成向上走和向下走,先预处理出每个点向上走和向下走的人数
      现在的问题就在于走不走得到了,在每个人的终点处打个标记,用vector存
      考虑从前往后带个桶走,走到一个终点就把它对应的起点取出来,这样走不到的在之前就已经被取出了

    • (Ti=1)
      答案就是这个点的子树中有多少满足(dep[v]=dep[u]+w[u])
      一个套路:
      还是开桶,进这个点的时候记录一下桶的元素个数,扫完子树再查一下,作差即可

    • (S_i=1)是什么?差分

    把上面三个拼起来,就有了正解的思路
    首先,一个人被观察到那么这个人一定经过了观测点,即这条路径经过观测点才有可能产生答案,
    于是这条路径的S或T一定在观测点的子树中,分开求S和T的贡献(这样就只需要考虑子树)
    把一条路径拆开,(S->lca)(lca->T)
    还是带个桶走,
    走到(S,T),把的贡献加进来,走到(lca)取出来

    • S的贡献:(dep[s]=dep[u]+w[u])
      每个S贡献唯一,直接开桶记
    • T的贡献:(dep[t]-dep[u]+w[u]=dep[s]+dep[t]-2dep[lca])
      消掉dep[t],变成(w[u]-dep[u]=dep[s]-2dep[lca])
      这样每个T有多种贡献,开vector记一下,
      还因为有可能是负的,所以开map存

    每个点的答案依然用(T_i=1)的套路求(ans[u]=t1[w[u]dep[u]]+t2[w[u]-dep[u]])
    (lca)处算了两遍贡献,特判(dep[st]==dep[lca]+w[lca])减掉1

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5;
    int re(){
    	int x=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*w;
    }
    int n,m,cnt,lca;
    int w[N],last[N],t[N],dep[N],top[N],son[N],fa[N],sz[N],ans[N],met[N];
    struct edge{int to,next;}e[N<<1];
    vector<int>v1[N],v2[N],f[N];
    map<int,int>vis;
    void link(int u,int v){
    	e[++cnt]=(edge){v,last[u]};last[u]=cnt;
    	e[++cnt]=(edge){u,last[v]};last[v]=cnt;
    }
    void dfs(int u){
    	sz[u]=1;
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa[u])continue;
    		dep[v]=dep[u]+1;
    		fa[v]=u;dfs(v);
    		sz[u]+=sz[v];
    		if(sz[v]>sz[son[u]])son[u]=v;
    	}
    }
    void dfs(int u,int tp){
    	top[u]=tp;
    	if(son[u])dfs(son[u],tp);
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v!=fa[u]&&v!=son[u])dfs(v,v);
    	}
    }
    void Query(int u,int v){
    	while(top[u]!=top[v]){
    		if(dep[top[u]]<dep[top[v]])swap(u,v);
    		u=fa[top[u]];
    	}
    	lca=dep[u]<dep[v]?u:v;
    }
    void dfs1(int u){
    	int s=v1[u].size(),pre=met[w[u]+dep[u]];
    	met[dep[u]]+=t[u];
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v!=fa[u])dfs1(v);
    	}
    	ans[u]+=met[w[u]+dep[u]]-pre;
    	for(int i=0;i<s;i++)met[dep[v1[u][i]]]--;
    }
    void dfs2(int u){
    	int s=v2[u].size(),pre=vis[w[u]-dep[u]];
    	int sx=f[u].size();
    	for(int i=0;i<sx;i++)vis[f[u][i]]++;
    	for(int i=last[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v!=fa[u])dfs2(v);
    	}
    	ans[u]+=vis[w[u]-dep[u]]-pre;
    	for(int i=0;i<s;i++)vis[v2[u][i]]--;
    }
    int main(){
    	n=re(),m=re();
    	for(int i=1,u,v;i<n;i++){
    		u=re(),v=re();link(u,v);
    	}
    	dfs(1);dfs(1,1);
    	for(int i=1;i<=n;i++)w[i]=re();
    	while(m--){
    		int st=re(),ed=re();
    		t[st]++;Query(st,ed);
    		f[ed].push_back(dep[st]-2*dep[lca]);
    		if(dep[st]==dep[lca]+w[lca])ans[lca]--;
    		v1[lca].push_back(st);
    		v2[lca].push_back(dep[st]-2*dep[lca]);
    	}
    	dfs1(1);dfs2(1);
    	for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    NDK开发一
    【转】Android NDK学习(2)Windows下NDK开发环境配置
    【转】Android NDK学习(3)使用Javah命令生成JNI头文件 .
    IDA 动态调试so
    Scrapy下载中间件的优先级(神踏马值越小优先级越高)
    二、深入asyncio协程(任务对象,协程调用原理,协程并发)
    python 可迭代对象,迭代器,生成器的区别及使用
    一、初识asyncio协程
    python多进程,进程池,数据共享,进程通信,分布式进程
    Scrapy的Request和Response对象
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/9936732.html
Copyright © 2011-2022 走看看