zoukankan      html  css  js  c++  java
  • Nauuo and ODT CF1172E

    一道LCT练手题,

    将询问离线,单独考虑每个颜色

    我们要求的就是至少经过某个颜色一次的路径数。

    每次计算变化量。

    考虑容斥,

    就是用总的路径数减去不经过的次数

    标记那个颜色的点为白色,其他的为黑色

    不经过的次数就是黑连通块的大小的平方。

    我们将所有的黑点向父亲连边,每个黑连通块实际上最上面有一个白点,我们维护子树的平方和,每次到顶上的白点统计答案即可。

    /*
    @Date    : 2019-08-14 08:07:13
    @Author  : Adscn (adscn@qq.com)
    @Link    : https://www.cnblogs.com/LLCSBlog
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define IL inline
    #define RG register
    #define gi getint()
    #define gc getchar()
    #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    IL int getint()
    {
    	RG int xi=0;
    	RG char ch=gc;
    	bool f=0;
    	while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    	while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    	return f?-xi:xi;
    }
    template<typename T>
    IL void pi(T k,char ch=0)
    {
    	if(k<0)k=-k,putchar('-');
    	if(k>=10)pi(k/10,0);
    	putchar(k%10+'0');
    	if(ch)putchar(ch);
    }
    const int N=4e5+7;
    int n,m;
    struct edge{
    	int v,nxt;
    }e[N<<1];
    int head[N],cnt;
    inline void add(int u,int v){e[++cnt]=(edge){v,head[u]},head[u]=cnt;}
    namespace LCT{
    	#define ls(x) (c[x][0])
    	#define rs(x) (c[x][1])
    	#define s(x,k) (c[x][k])
    	int val[N],f[N],siz[N],si[N];
    	long long siz2[N],si2[N];//si 轻儿子
    	int c[N][2];
    	inline long long sqr(int x){return 1ll*x*x;}
    	inline bool ws(int x,int p){return ls(p)^x;}
    	inline bool nroot(int x){return ls(f[x])==x||rs(f[x])==x;}
    	inline void pushup(int x){
    		siz[x]=siz[ls(x)]+siz[rs(x)]+si[x]+1;
    		siz2[x]=sqr(siz[ls(x)])+sqr(siz[rs(x)])+si2[x];
    	}
    	inline void rotate(int x)
    	{
    		int p=f[x],g=f[p];
    		int t=ws(x,p),w=s(x,!t);
    		if(nroot(p))s(g,ws(p,g))=x;s(x,!t)=p;s(p,t)=w;
    		if(w)f[w]=p;f[p]=x;f[x]=g;
    		pushup(p);
    	}
    	inline void Splay(int x){
    		while(nroot(x)){
    			int p=f[x],g=f[p];
    			if(nroot(p))rotate(ws(x,p)^ws(p,g)?x:p);
    			rotate(x);
    		}
    		pushup(x);
    	}
    	inline void access(int x){
    		for(int y=0;x;x=f[y=x])
    			Splay(x),si[x]+=siz[rs(x)]-siz[y],si2[x]+=sqr(siz[rs(x)])-sqr(siz[y]),rs(x)=y,pushup(x);
    	}
    	inline int findroot(int x){
    		access(x),Splay(x);
    		while(ls(x))x=ls(x);
    		return Splay(x),x;
    	}
    	inline void link(int u,int v)
    	{
    		access(v),Splay(v);Splay(u);
    		si[v]+=siz[u],si2[v]+=sqr(siz[u]);
    		pushup(f[u]=v);
    	}
    	inline void cut(int u,int v)
    	{
    		access(v),Splay(v);Splay(u);
    		si[v]-=siz[u],si2[v]-=sqr(siz[u]),f[u]=0;
    		pushup(v);
    	}
    }
    using namespace LCT;
    int fa[N],col[N];
    long long ans[N];
    inline void dfs(int p){for(int i=head[p];~i;i=e[i].nxt)if(e[i].v^fa[p])fa[e[i].v]=p,dfs(e[i].v);}
    struct operation{
    	int tim,u,opt;
    };
    vector<operation>opt[N];
    int main(void)
    {
    	#ifndef ONLINE_JUDGE
    //	File("color");
    	#endif
    	memset(head,cnt=-1,sizeof head);
    	n=gi,m=gi;
    	for(int i=1;i<=n;++i)col[i]=gi;
    	for(int i=1;i<n;++i)
    	{
    		int u=gi,v=gi;
    		add(u,v),add(v,u);
    	}
    	dfs(1);fa[1]=n+1;
    	fill(siz+1,siz+n+2,1);
    	for(int i=1;i<=n;++i)link(i,fa[i]);
    //	for(int i=1;i<=n;++i)cout<<fa[i]<<" ";
    //	cout<<endl;
    	for(int i=1;i<=n;++i)opt[col[i]].push_back((operation){0,i,0});
    	for(int i=1;i<=m;++i)
    	{
    		int u=gi,x=gi;
    		opt[col[u]].push_back((operation){i,u,1});
    		opt[col[u]=x].push_back((operation){i,u,0});
    	}
    	for(int i=1;i<=n;++i)opt[col[i]].push_back((operation){m+1,i,1});
    	for(int i=1;i<=n;++i)
    		for(auto&& x:opt[i]){
    			int t=x.tim,u=x.u,p=findroot(fa[u]);
    			if(x.opt)
    			{
    				Splay(p),Splay(u);
    				ans[t]+=siz2[p]+siz2[u];
    				link(u,fa[u]);
    				Splay(p),ans[t]-=siz2[p];
    			}
    			else
    			{
    				Splay(p),ans[t]+=siz2[p];
    				cut(u,fa[u]);
    				Splay(p),Splay(u),ans[t]-=siz2[p]+siz2[u];
    			}
    		}
    	for(int i=1;i<=m;++i)ans[i]+=ans[i-1];
    	for(int i=0;i<=m;++i)pi(ans[i],'
    ');
    	return 0;
    }
    
  • 相关阅读:
    一些常用的接口地址
    1-项目启动
    事件处理优化
    如何javascript获取css中的样式
    mysql编程--创建函数出错的解决方案
    mysql编程---函数
    mysql---数据控制语言(用户及其权限管理)
    php与mysql的常规使用
    php数组的使用
    php函数的使用
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/11355776.html
Copyright © 2011-2022 走看看