zoukankan      html  css  js  c++  java
  • Codeforces 571D. Campus 题解

    题目链接:D. Campus

    题目大意:洛谷


    题解:发现合并很不好搞,所以先把最后的树建出来,然后将操作转换为对子树的操作。所以可以在子树上打上标记,因为赋值会撤销之前一切操作的影响,所以我们的问题就转换为了查询上一次被覆盖的时间和在某一个时间后的操作结果。

    所以对两个树 DFS,然后拿树状数组做。

    时间复杂度 (O(n+mlog m))

    代码:

    #include <vector>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    constexpr int Maxn=500000;
    struct Tree{
    	int n;
        vector<int> parent,lc,rc,id;
        vector<vector<int> > mod;
        void init(int n){
        	parent.assign(2*n-1,-1);
    		lc.assign(2*n-1,-1);
    		rc.assign(2*n-1,-1);
    		id.resize(n);
    		iota(id.begin(),id.end(),0);
    		mod.resize(2*n-1);
    	}
    };
    int n,m;
    Tree t1,t2;
    vector<vector<int> > query;
    vector<int> lb,sz;
    vector<ll> ans;
    ll fen[Maxn+5];
    void add(int x,int y){
    	for(int i=x+1;i<=Maxn;i+=(i&(-i))){
    		fen[i]+=y;
    	}
    }
    ll sum(int x){
    	ll res=0;
    	for(int i=x;i>0;i-=(i&(-i))){
    		res+=fen[i];
    	}
    	return res;
    }
    ll sum(int l,int r){
    	return sum(r)-sum(l);
    }
    int getLeft(int x){
    	int s=sum(x);
    	x=0;
    	for(int i=(1<<18);i>0;i>>=1){
    		if(x+i<=Maxn&&fen[x+i]<s){
    			x+=i;
    			s-=fen[x];
    		}
    	}
    	return x;
    }
    void dfs_1(int u){
    	for(int i:t2.mod[u]){
    		add(i,1);
    	}
    	if(u<n){
    		for(int i:query[u]){
    			lb[i]=getLeft(i);
    		}
    	}
    	else{
    		dfs_1(t2.lc[u]);
    		dfs_1(t2.rc[u]);
    	}
    	for(int i:t2.mod[u]){
    		add(i,-1);
    	}
    }
    void dfs_2(int u){
    	for(int i:t1.mod[u]){
    		add(i,sz[u]);
    	}
    	if(u<n){
    		for(int i:query[u]){
    			ans[i]=sum(lb[i],i);
    		}
    	}
    	else{
    		dfs_2(t1.lc[u]);
    		dfs_2(t1.rc[u]);
    	}
    	for(int i:t1.mod[u]){
    		add(i,-sz[u]);
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	t1.init(n),t2.init(n);
    	query.resize(n);
    	lb.resize(m);
    	sz.resize((n<<1)-1);
    	for(int i=0;i<(n<<1)-1;i++){
    		sz[i]=1;
    	}
    	ans.resize(m);
    	for(int i=0;i<m;i++){
    		ans[i]=-1;
    	}
    	int c1=0,c2=0;
    	for(int i=0;i<m;i++){
    		char op,qu[5];
    		scanf("%s",qu);
    		op=(*qu);
    		if(op=='U'){
    			int a,b;
    			scanf("%d%d",&a,&b);
    			a--;
    			b--;
    			int p=n+(c1++);
    			t1.parent[t1.id[a]]=t1.parent[t1.id[b]]=p;
    			t1.lc[p]=t1.id[a];
    			t1.rc[p]=t1.id[b];
    			t1.id[a]=p;
    			sz[p]=sz[t1.lc[p]]+sz[t1.rc[p]];
    		}
    		else if(op=='M'){
    			int a,b;
    			scanf("%d%d",&a,&b);
    			a--;
    			b--;
    			int p=n+(c2++);
    			t2.parent[t2.id[a]]=t2.parent[t2.id[b]]=p;
    			t2.lc[p]=t2.id[a];
    			t2.rc[p]=t2.id[b];
    			t2.id[a]=p;
    		}
    		else if(op=='A'){
    			int x;
    			scanf("%d",&x);
    			x--;
    			t1.mod[t1.id[x]].push_back(i);
    		}
    		else if(op=='Z'){
    			int x;
    			scanf("%d",&x);
    			x--;
    			t2.mod[t2.id[x]].push_back(i);
    		}
    		else{
    			int x;
    			scanf("%d",&x);
    			x--;
    			query[x].push_back(i);
    		}
    	}
    	for(int i=0;i<n+c2;i++){
    		if(t2.parent[i]==-1){
    			dfs_1(i);
    		}
    	}
    	for(int i=0;i<n+c1;i++){
    		if(t1.parent[i]==-1){
    			dfs_2(i);
    		}
    	}
    	for(int i=0;i<m;i++){
    		if(ans[i]!=-1){
    			printf("%lld
    ",ans[i]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Scrapy shell调试返回403错误
    android 获取 imei号码
    查找目录下的所有文件中是否含有某个字符串
    自动生成和配置ES的安全证书
    docker构建本地私有镜像
    ELK容器化部署
    Rancher使用基础知识1
    jenkins自动打包部署流水线
    ansible管理windows主机
    jenkins集成gitlab自动构建打包
  • 原文地址:https://www.cnblogs.com/withhope/p/13670254.html
Copyright © 2011-2022 走看看