zoukankan      html  css  js  c++  java
  • 树分块&&树上莫队&&树上带修莫队

    (王室联邦 树分块的裸体  xjb跑dfs就行了

    树上莫队个人感觉就是dfs序+普通莫队就可以了

    经典例题http://www.spoj.com/problems/COT2/

    #include <bits/stdc++.h>
    #define ll long long
    #define N 40005 
    #define MAXN 100005
    using namespace std;
    ll readll(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int readint(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    int n,q,size,p[N<<1],cnt1,cnt2,b[N<<1],cnt3,cnt;
    int begin[N],last[N];
    ll a[N];
    vector<ll>vec;
    vector<int>edge[N];
    int num[N],son[N],dep[N],pre[N];
    void dfs(int v,int fa,int deep){
    	b[++cnt3]=v;num[v]=1,dep[v]=deep+1;pre[v]=fa;begin[v]=cnt3;
    	for(int i=0;i<edge[v].size();i++){
    		int u=edge[v][i];
    		if(u!=fa){
    			dfs(u,v,deep+1);
    			num[v]+=num[u];
    			if(son[v]==-1||num[u]>num[son[v]]) son[v]=u;
    		}
    	}
    	b[++cnt3]=v;last[v]=cnt3;
    }
    int tp[N];
    void dfs2(int v,int td){
    	tp[v]=td;
    	if(son[v]!=-1) dfs2(son[v],td);
    	for(int i=0;i<edge[v].size();i++){
    		int u=edge[v][i];
    		if(u!=pre[v]&&u!=son[v]) dfs2(u,u);
    	}
    }
    typedef struct node{
    	int l,r,biao,lca,flag;
    	friend bool operator <(node aa,node bb){
    		if(p[aa.l]==p[bb.l]) return aa.r<bb.r;
    		return p[aa.l]<p[bb.l];
    	}
    }node;
    int Lca(int u,int v){
    	int uu=tp[u];int vv=tp[v];
    	while(uu!=vv){
    		if(dep[uu]<dep[vv]){
    			swap(uu,vv);swap(u,v);
    		}
    		u=pre[uu];uu=tp[u];
    	}
    	if(dep[u]>dep[v]) swap(u,v);
    	return u;
    }
    node d[MAXN];int cont[N],vis[N];
    int ans[MAXN],sum;
    void check(int R){
    		vis[b[R]]^=1;
    		if(vis[b[R]]){
    			cont[a[b[R]]]++;
    			if(cont[a[b[R]]]==1) sum++;
    		}
    		else{
    			cont[a[b[R]]]--;
    			if(cont[a[b[R]]]==0) sum--;
    		}
    }
    int main(){
    	ios::sync_with_stdio(false);cnt1=0;cnt2=0;cnt3=0;cnt=0;
    	n=readint();q=readint();size=(int)sqrt(2*n);
    	for(int i=1;i<=n;i++) son[i]=-1;
    	for(int i=1;i<=n;i++) a[i]=readll(),vec.push_back(a[i]);
    	for(int i=1;i<=2*n;i++) p[i]=(i-1)/size+1;
    	sort(vec.begin(),vec.end());
    	int t=unique(vec.begin(),vec.end())-vec.begin();
    	for(int i=1;i<=n;i++) a[i]=lower_bound(vec.begin(),vec.begin()+t,a[i])-vec.begin()+1;
    	int u,v;
    	for(int i=1;i<n;i++){
    		u=readint();v=readint();
    		edge[u].push_back(v);edge[v].push_back(u);
    	}
    	dfs(1,-1,0);dfs2(1,1);
    	int l,r;
    	for(int i=1;i<=q;i++){
    		l=readint();r=readint();d[i].lca=Lca(l,r);d[i].biao=i;
    		if(d[i].lca==l||d[i].lca==r) d[i].l=min(begin[l],begin[r]),d[i].r=max(begin[l],begin[r]),d[i].flag=1;
    		else{
    			if(begin[l]<begin[r]) d[i].l=last[l],d[i].r=begin[r];
    			else d[i].l=last[r],d[i].r=begin[l];
    		}
    	}
    	sort(d+1,d+q+1);
    	int L=1,R=0;sum=0;
    	for(int i=1;i<=q;i++){
    		while(R>d[i].r){
    			check(R);R--;
    		}
    		while(R<d[i].r){
    			R++;check(R);
    		}
    		while(L>d[i].l){
    			L--;check(L);
    		}
    		while(L<d[i].l){
    			check(L);L++;
    		}
    		if(d[i].flag) ans[d[i].biao]=sum;
    		else{
    			ans[d[i].biao]=sum;
    			if(!cont[a[d[i].lca]]) ans[d[i].biao]++;
    		}
    	}
    	for(int i=1;i<=q;i++) printf("%d
    ",ans[i]);
    	return 0;
    }
    

     (对于树上带修莫队  会了树上莫队  加上一个带修操作 和普通带修莫队没啥区别 复杂度其他证明也基本类似

    经典例题http://www.lydsy.com/JudgeOnline/problem.php?id=3052

    #include <bits/stdc++.h>
    #define ll long long
    #define N 100005
    #define MAXN 1000005
    #define pii pair<int,int> 
    using namespace std;
    ll readll(){
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int readint(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    int n,m,q;
    int a[N],p[N<<1],c[N];
    ll V[N],W[N];
    int b[N<<1],begin[N],last[N],cnt,fa[N],dep[N],size;
    int num[N],son[N],first[N],cnt1;
    pii Next[N<<1];
    void add(int u,int v){
    	Next[++cnt1].first=first[u];Next[cnt1].second=v;first[u]=cnt1;
    	Next[++cnt1].first=first[v];Next[cnt1].second=u;first[v]=cnt1;
    }
    void dfs(int u,int pre,int deep){
    	num[u]=1;dep[u]=deep+1;fa[u]=pre;b[++cnt]=u;begin[u]=cnt;
    	for(int i=first[u];i!=-1;i=Next[i].first){
    		int v=Next[i].second;
    		if(v!=pre){
    			dfs(v,u,deep+1);
    			num[u]+=num[v];
    			if(son[u]==-1||num[v]>num[son[u]]) son[u]=v;
    		}
    	}
    	b[++cnt]=u;last[u]=cnt;
    }
    int tp[N];
    void dfs1(int v,int td){
    	tp[v]=td;
    	if(son[v]!=-1) dfs1(son[v],td);
    	for(int i=first[v];i!=-1;i=Next[i].first){
    		int u=Next[i].second;
    		if(u!=fa[v]&&u!=son[v]) dfs1(u,u);
    	} 
    }
    int Lca(int u,int v){
    	int uu=tp[u];int vv=tp[v];
    	while(uu!=vv){
    		if(dep[uu]<dep[vv]){
    			swap(uu,vv);swap(u,v);
    		}
    		u=fa[uu];uu=tp[u];
    	}
    	if(dep[u]>dep[v]) swap(u,v);
    	return u;
    } 
    typedef struct node{
    	int l,r,lca,biao;int t;bool flag;
    	friend bool operator <(node aa,node bb){
    		if(p[aa.l]==p[bb.l]&&p[aa.r]==p[bb.r]) return aa.t<bb.t;
    		else if(p[aa.l]==p[bb.l]) return p[aa.r]<p[bb.r];
    		else return p[aa.l]<p[bb.l];
    	}
    }node;
    node d[N];int vis[N],cont[1000006];
    pii to[N],past[N];
    ll ans[N],sum;
    void work(int pos){
    	vis[b[pos]]^=1;
    	if(vis[b[pos]]){
    		cont[a[b[pos]]]++;sum+=1ll*W[cont[a[b[pos]]]]*V[a[b[pos]]];
    	}
    	else{
    		cont[a[b[pos]]]--;sum-=1ll*W[cont[a[b[pos]]]+1]*V[a[b[pos]]];
    	}
    }
    void update(int l,int r,int t){
    	int u=to[t].first;int vul=to[t].second;
    //	cout<<u<<"----"<<vul<<endl;
    	int t1=begin[u];int t2=last[u];
    	int cp=0;int pos;
    	if(t1>=l&&t1<=r) cp++,pos=t1;
    	if(t2>=l&&t2<=r) cp++,pos=t2;
    //	cout<<a[b[pos]]<<" "<<cp<<endl;
    	if(cp==1){
    		cont[a[b[pos]]]--;;sum-=1ll*W[cont[a[b[pos]]]+1]*V[a[b[pos]]];
    		//cout<<sum<<endl;
    		cont[vul]++;sum+=1ll*W[cont[vul]]*V[vul];
    	}
    	a[u]=vul;
    }
    void restore(int l,int r,int t){
    	int u=past[t].first;int vul=past[t].second;
    	int t1=begin[u];int t2=last[u];
    	int cp=0;int pos;
    	if(t1>=l&&t1<=r) cp++,pos=t1;
    	if(t2>=l&&t2<=r) cp++,pos=t2;
    	if(cp==1){
    		cont[a[b[pos]]]--;;sum-=1ll*W[cont[a[b[pos]]]+1]*V[a[b[pos]]];
    		cont[vul]++;sum+=1ll*W[cont[vul]]*V[vul];
    	}
    	a[u]=vul;
    }
    int main(){
    	ios::sync_with_stdio(false);cnt=cnt1=0;
    	//cout<<size<<endl;
    	n=readint();m=readint();q=readint();
    	size=(int)pow(2*n,2.0/3);	
    	for(int i=1;i<=2*n;i++) p[i]=(i-1)/size+1;;
    	for(int i=1;i<=n;i++) son[i]=first[i]=-1;
    	for(int i=1;i<=m;i++) V[i]=readll();
    	for(int i=1;i<=n;i++) W[i]=readll();
    	int u,v;
    	for(int i=1;i<n;i++){
    		u=readint();v=readint();
    		add(u,v);
    	}
    	for(int i=1;i<=n;i++) c[i]=a[i]=readint();
    	dfs(1,-1,0);dfs1(1,1);
    	//for(int i=1;i<=2*n;i++) cout<<b[i]<<" ";
    	//cout<<endl;
    	int op,l,r;int T=0;u=0;
    	for(int i=1;i<=q;i++){
    		op=readint();l=readint();r=readint();
    		if(op==0){
    			to[++T].first=l;to[T].second=r;
    			past[T].first=l;past[T].second=c[l];
    			c[l]=r;
    		}
    		else{
    			d[++u].lca=Lca(l,r);d[u].biao=u;d[u].t=T;
    			if(d[u].lca==l||d[u].lca==r) d[u].l=min(begin[l],begin[r]),d[u].r=max(begin[l],begin[r]);
    			else{
    				if(begin[l]>begin[r]) swap(l,r);
    				d[u].l=last[l];d[u].r=begin[r];d[u].flag=1;
    			}
    		}
    	}
    //	cout<<u<<endl;
    	sort(d+1,d+u+1);int L=1,R=0,t=0;sum=0;
    //	for(int i=1;i<=u;i++){
    //		cout<<d[i].l<<" "<<d[i].r<<" "<<d[i].lca<<" "<<d[i].t<<endl;
    //	}
    	//for(int i=1;i<=2*n;i++) cout<<b[i]<<" ";
    //	cout<<endl;
    	for(int i=1;i<=u;i++){
    	//	cout<<d[i].l<<"====="<<d[i].r<<" "<<d[i].t<<"======"<<d[i].biao<<endl;
    		while(t>d[i].t){
    			restore(L,R,t);t--;
    		}
    		while(t<d[i].t){
    			t++;update(L,R,t);
    		}
    		while(R>d[i].r){
    			work(R);R--;
    		}
    		while(R<d[i].r){
    			R++;work(R);
    		}
    		while(L<d[i].l){
    			work(L);L++;
    		}
    		while(L>d[i].l){
    			L--;work(L);
    		}
    		ans[d[i].biao]=sum;
    		if(d[i].flag) ans[d[i].biao]+=(W[cont[a[d[i].lca]]+1]*V[a[d[i].lca]]);
    	}
    	for(int i=1;i<=u;i++) printf("%lld
    ",ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    [UE4]九宫格图片拉伸
    [UE4]IsValid方法妙用
    [UE4]蓝图函数库
    [UE4]创建KillInfoPanel
    [UE4]条件语句Select
    [UE4]控件模板参数
    [UE4]控件模板
    [UE4]不推荐的UI更新方式
    [UE4]事件驱动的UI更新:事件调度器
    [UE4]更新UI的三种方式
  • 原文地址:https://www.cnblogs.com/wang9897/p/8456993.html
Copyright © 2011-2022 走看看