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;
    }
    
  • 相关阅读:
    解决xcode5升级后,Undefined symbols for architecture arm64:问题
    第8章 Foundation Kit介绍
    app 之间发送文件 ios
    iphone怎么检测屏幕是否被点亮 (用UIApplication的Delegate)
    CRM下载对象一直处于Wait状态的原因
    错误消息Customer classification does not exist when downloading
    How to resolve error message Distribution channel is not allowed for sales
    ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX这些东东是什么鬼
    有了Debug权限就能干坏事?小心了,你的一举一动尽在系统监控中
    SAP GUI和Windows注册表
  • 原文地址:https://www.cnblogs.com/sdzwyq/p/9936732.html
Copyright © 2011-2022 走看看