zoukankan      html  css  js  c++  java
  • P1600 天天爱跑步

    update 2019.9.29

    分解成为(u->lca)(lca->v)
    得到两个式子,需要统计子树内部的信息。
    用差分维护下,差分维护类似于这个前置题

    #include <bits/stdc++.h>
    using namespace std;
    const int _=5e5+7;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,m,w[_],S[_],T[_],lca[_],tong[_*3],ans[_];
    struct node {int v,nxt,q;}e[_<<1];
    struct edge {int x,y;edge(int a=0,int b=0) {x=a,y=b;}};
    vector<edge> ad[_*4];
    int head[_],tot;
    void add(int u,int v) {
    	e[++tot].v=v;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    int son[_],dep[_],fa[_],siz[_],top[_];
    void dfs1(int u,int f) {
    	fa[u]=f;
    	dep[u]=dep[f]+1;
    	siz[u]=1;
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(v==f) continue;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		if(siz[son[u]]<siz[v]) son[u]=v;
    	}
    }
    void dfs2(int u,int topf) {
    	top[u]=topf;
    	if(!son[u]) return;
    	dfs2(son[u],topf);
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(!top[v]) dfs2(v,v);
    	}
    }
    int LCA(int x,int y) {
    	while(top[x]!=top[y]) {
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		x=fa[top[x]];
    	} return dep[x]<dep[y]?x:y;
    }
    void solve1(int u,int fa) {
    	int A=tong[dep[u]+w[u]];
    	for(int i=0;i<(int)ad[u].size();++i)
    		tong[ad[u][i].x]+=ad[u][i].y;
    	for(int i=head[u];i;i=e[i].nxt)
    		if(e[i].v!=fa) solve1(e[i].v,u);
    	int B=tong[dep[u]+w[u]];
    	ans[u]+=B-A;
    }
    void solve2(int u,int fa) {
    	int A=tong[w[u]-dep[u]+2*n];
    	for(int i=0;i<(int)ad[u].size();++i)
    		tong[ad[u][i].x]+=ad[u][i].y;
    	for(int i=head[u];i;i=e[i].nxt)
    		if(e[i].v!=fa) solve2(e[i].v,u);
    	int B=tong[w[u]-dep[u]+2*n];
    	ans[u]+=B-A;
    }
    int main() {
    	n=read(),m=read();
    	for(int i=1;i<n;++i) {
    		int u=read(),v=read();
    		add(u,v),add(v,u);
    	}
    	for(int i=1;i<=n;++i) w[i]=read();
    	dfs1(1,0),dfs2(1,1);
    	for(int i=1;i<=m;++i) S[i]=read(),T[i]=read(),lca[i]=LCA(S[i],T[i]);
    	for(int i=1;i<=m;++i) {
    		ad[S[i]].push_back(edge(dep[S[i]],1));
    		ad[fa[lca[i]]].push_back(edge(dep[S[i]],-1));
    	}
    	solve1(1,0);
    	for(int i=1;i<=n*3;++i) ad[i].clear();
    	for(int i=1;i<=m;++i) {
    		ad[lca[i]].push_back(edge(dep[S[i]]-2*dep[lca[i]]+2*n,-1));
    		ad[T[i]].push_back(edge(dep[S[i]]-2*dep[lca[i]]+2*n,1));
    	}
    	solve2(1,0);
    	for(int i=1;i<=n;++i) printf("%d ",ans[i]);
    	return 0;
    }
    

    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;
    }
    
    
  • 相关阅读:
    Oracle+Ado.Net(四)
    Oracle+Ado.Net(三)
    json-server 详解
    在线字体图标
    HTML页面模板代码
    CSS样式重置
    WEB前端开发流程总结
    大前端-全栈-node+easyui+express+vue+es6+webpack+react
    大前端全栈CSS3移动端开发
    jQuery学习
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9681689.html
Copyright © 2011-2022 走看看