zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 56 (Rated for Div. 2) E(1093E) Intersection of Permutations (树套树,pb_ds)

    题意和分析在之前的链接中有:https://www.cnblogs.com/pkgunboat/p/10160741.html

    之前补题用三维偏序的cdq的分治A了这道题,但是感觉就算比赛再次遇到类似的题可能写不出cdq的代码。。。这次算是自己独立A的了。。。

    如果这题不卡常的话,什么树套什么树都可以,为了节省空间以及提高效率,我在外层写一个树状数组,树状数组的每一个节点用pb_ds的红黑树维护(红黑大法好),这样查询效率比较高。

    为了方便红黑树的区间操作,每颗树插入1个负无穷,1个正无穷。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    #include<ext/pb_ds/assoc_container.hpp>
    #include<ext/pb_ds/tree_policy.hpp>
    #define lowbit(x) (x&(-x))
    using namespace std;
    using namespace __gnu_pbds;
    const int maxn=200010;
    int a[maxn],b[maxn],pos[maxn],mp[maxn];
    __gnu_pbds::tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> t[maxn];
    __gnu_pbds::tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>::iterator itl,itr;
    int n,m,ql,qr;
    int query(int x){
    	int ans;
    	itl=t[x].lower_bound(ql);
    	itr=t[x].upper_bound(qr);
    	return  t[x].order_of_key(*itr)-t[x].order_of_key(*itl);
    	
    }
    int ask(int x){
    	int ans=0;
    	for(;x;x-=lowbit(x))
    		ans+=query(x);
    	return ans;
    }
    void build(int n){
    	for(int i=1;i<=n;i++){
    		for(int j=i-lowbit(i)+1;j<=i;j++)
    			t[i].insert(mp[j]);
    		t[i].insert(-INF);
    		t[i].insert(INF);
    	}
    		
    }
    void maintain(int x,int y){
    	if(y<0){
    		if(t[x].find(-y)!=t[x].end())
    			t[x].erase(-y);
    	}
    	else{
    		t[x].insert(y);
    	}
    }
    void add(int x,int y){
    	for(;x<=n;x+=lowbit(x))
    		maintain(x,y);
    }
    int main(){
    	int l,r,x,op;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&x);
    		pos[x]=i;
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%d",&x);
    		mp[i]=pos[x];
    	}
    	build(n);
    	while(m--){
    		scanf("%d",&op);
    		if(op==1){
    			scanf("%d%d%d%d",&ql,&qr,&l,&r);
    			printf("%d
    ",ask(r)-ask(l-1));
    		}
    		else{
    			scanf("%d%d",&l,&r);
    			add(l,-mp[l]);
    			add(r,-mp[r]);
    			swap(mp[l],mp[r]);
    			add(l,mp[l]);
    			add(r,mp[r]);
    		}
    	}
    }
    

    代码比较:

    cdq分治:                                        

          

    树套树:

     

     明显cdq分治更快,而树套树的内存占用更少(不太科学)。

    以本辣鸡的码力,如果要用线段树这些常数比较大的树应该要超时。。。

  • 相关阅读:
    剑指offer-第二章排序之年龄排序
    剑指offer—第二章算法之快速排序
    java小程序(课堂作业02)
    关于java的一些小知识(课程作业01)
    Java从命令行接受多个数字并求和
    《大道至简》第一章读后感及伪代码
    大道至简读后感
    GCPC 2013_A Boggle DFS+字典树 CSU 1457
    Aizu 2155 Magic Slayer 背包DP
    UVALive 4255 Guess
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10220821.html
Copyright © 2011-2022 走看看