• 8.1


    索引

    学习

    • fhq treap

    复习

    • 欧拉回路

    STL神器

    • 一些可能很常用的函数介绍(持续更新)
      • replace()
      • random_shuffle()
      • nth_element()

      • find()
      • set_union() 求并集
      • set_intersection() 求交集
    • priority_queue是支持自定义比较函数的

    奇技淫巧

    • 两行vector 求逆序对
    • 六行vector 过平衡树板子

    fhq treap

    /*
    reference:
    	https://www.luogu.org/blog/yhzq/solution-p3369
    	https://fop_zz.coding.me/2018/03/15/treap/#P3165-%E6%9C%BA%E6%A2%B0%E8%87%82%E6%8E%92%E5%BA%8F
    translation:
    	
    solution:
    
    trigger:
    	
    note:
    	*
    date:
    	2019.08.01
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,b) for(ll i=a;i<=b;++i)
    #define dwn(i,a,b) for(ll i=a;i>=b;--i) 
    template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    
    #define N 500001
    int tot,siz[N],val[N],rnd[N],son[N][2];
    int x,y,n,rt;  
    
    void upd(int x){siz[x]=1+siz[son[x][0]]+siz[son[x][1]];}
    
    int new_node(int x){siz[++tot]=1;val[tot]=x;rnd[tot]=rand();return tot;}
    
    void split(int now,int k,int &x,int &y){
    	if(!now)x=y=0;
    	else{
    		if(val[now]<=k)
    			x=now,split(son[now][1],k,son[x][1],y);
    		else 
    			y=now,split(son[now][0],k,x,son[y][0]);
    		upd(now);
    	}
    }
    
    int merge(int x,int y){
    	if(!x || !y)return x^y;
    	if(rnd[x]<rnd[y]){
    		son[x][1]=merge(son[x][1],y);
    		upd(x);
    		return x;
    	}
    	else {
    		son[y][0]=merge(x,son[y][0]);
    		upd(y);
    		return y;
    	}
    }
    
    int kth(int x,int k){
    	while(1){
    		if(siz[son[x][0]]>=k)
    			x=son[x][0];
    		else if(siz[son[x][0]]+1==k)
    			return x;
    		else
    			k-=siz[son[x][0]]+1,x=son[x][1];
    	}
    }
    
    int main(){
    	#ifdef WIN32
    	freopen("fhq.txt","r",stdin);  
        #endif
    	//srand(time(0));  
    	srand((unsigned)time(NULL));
        rd(n);
        rep(i,1,n){  
            int op,a;rd(op),rd(a);
            if(op==1){
            	split(rt,a,x,y);
            	rt=merge(merge(x,new_node(a)),y);
    		}
            if(op==2){
            	int z=0;
            	split(rt,a,x,z);
            	split(x,a-1,x,y);
    			y=merge(son[y][0],son[y][1]);//不能写成x
    			rt=merge(merge(x,y),z); 
    		}
    		if(op==3){
    			split(rt,a-1,x,y);
    			printf("%d
    ",siz[x]+1);
    			rt=merge(x,y);
    		}
            if(op==4)  
                printf("%d
    ",val[kth(rt,a)]);
            if(op==5){
            	split(rt,a-1,x,y);
            	printf("%d
    ",val[kth(x,siz[x])]);
            	rt=merge(x,y);
    		}
    		if(op==6){
    			split(rt,a,x,y);
    			printf("%d
    ",val[kth(y,1)]);
    			rt=merge(x,y);
    		}
        }  
        return 0;
    }
    

    vector 求逆序对

    首先我们想一下冒泡排序的过程,我们不难发现,对于每一个元素,我们实际上是让他不停的和前面的元素比较,交换。

    也正是因为这个过程决定了在冒泡排序的过程中:一个位置的数的前面的数一定是递增的(从小到大排的话)

    那么我们在交换的时候,直接二分找到一个合适的位置,插入即可

    这个很显然可以用平衡树Vector实现

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,b) for(ll i=a;i<=b;++i)
    #define dwn(i,a,b) for(ll i=a;i>=b;--i) 
    template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    
    int n,m,ans,a[100001];
    vector<int>v;
    int main(){
    	rd(n);
    	rep(i,1,n)rd(a[i]); 
        rep(i,1,n){
            int now=upper_bound(v.begin(),v.end(),a[i])-v.begin();
            ans=ans+i-now-1;
    		v.insert(v.begin()+now,a[i]);
        }
        printf("%d",ans);
        return 0;
    }
    

    vector 求平衡树

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,b) for(ll i=a;i<=b;++i)
    #define dwn(i,a,b) for(ll i=a;i>=b;--i) 
    template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    
    vector<int>v;
    int n,op,x;
    int main(){
        v.reserve(100001);
        rd(n);
        while(n--){
        	rd(op),rd(x);
            if(op==1)v.insert(lower_bound(v.begin(),v.end(),x),x);
            if(op==2)v.erase(lower_bound(v.begin(),v.end(),x));
            if(op==3)printf("%d
    ",lower_bound(v.begin(),v.end(),x)-v.begin()+1);
            if(op==4)printf("%d
    ",v[x-1]);
            if(op==5)printf("%d
    ",v[lower_bound(v.begin(),v.end(),x)-v.begin()-1]);
            if(op==6)printf("%d
    ",v[upper_bound(v.begin(),v.end(),x)-v.begin()]);
        }
        return 0;
    }
    

    复习欧拉回路

    性质

    *如果图中奇数度的顶点个数小于等于2,则一定存在欧拉回路

    *在无向图中每个顶点的度都是偶数,则一定存在回路

    *在有向图中,每个节点的入度等于出度,则存在回路

    例题

    • 瑞瑞的木棍
    使用并查集维护经过点的个数
    设x为成功合并的次数,n为点数
    则整张图含欧拉路当且仅当x>=n−1且奇度数点为0或2
    
    顺便提一下
    pbds真是个好东西
    

    一些可能很常用的函数介绍(持续更新)

    replace

    • replace(初始位置,结束位置,替换字符串);

    find

    • (母字符串).find(子字符串,起始位置)

    如果没有设置起始位置默认为从头开始。如果返回-1的话表示该字符串中没有查询的字符串出现。qwq
    当然,如果读入的时候往右移动了一位,记得起始位置也要变一变qwqwq

    random_shuffle()

    • random_shuffle(起始位置,结束位置)
      将数组打乱。

    nth_element

    • nth_element(起始位置,所求位置,结束位置)
    它的用法是nth_element(a+l,a+k,a+r)
    这样它会使a这个数组中区间[l,r)内的第k小的元素处在第k个位置上(相对位置)
    但是它并不保证其他元素有序!
    
    不过根据网友的实验,貌似在vs上是有序的,不过在dev中是无序的
    
    时间复杂度:O(n)
    #include<bits/stdc++.h>
    using namespace std;
    
    int a[15]={0,100,200,500,700,300,400,100};
    
    int main(){
    	nth_element(a+1,a+4,a+9);
        for(int i=1;i<=8;++i)
    		printf("%d ", a[i]);
        return 0;
    }
    

    时间复杂度为O(N),比所求数小的数都在这个数前面,比所求数大的数都在这个数后面,但是不保证有序。
    最大的应用价值为求中位数

    set_union() 求并集

    set_intersection() 求交集

    以下是程序演示

    
    #include<bits/stdc++.h>
    using namespace std;
    int main(){
        set<int>s1,s2,s3,s4;
        s1.insert(1);
        s1.insert(2);
        s2.insert(2);
        s2.insert(4);
        set_union(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
        set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(s4,s4.begin()));
        for(set<int>::iterator it=s3.begin();it!=s3.end();it++)
            cout<<*it<<" ";
        cout<<endl;
        for(set<int>::iterator it=s4.begin();it!=s4.end();it++)
            cout<<*it<<" ";
    }
    

    priority_queue支持自定义比较函数

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,b) for(ll i=a;i<=b;++i)
    #define dwn(i,a,b) for(ll i=a;i>=b;--i) 
    template <typename T> inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int n=5;
    struct node{
        int x,y;
        node(){x=y=0;}
        node(int a,int b){x=a;y=b;}
    	bool operator<(const node &a)const{
    	    if(x!=a.x)return x>a.x;
    	    return y<a.y;
    	}
    };
    priority_queue<node>q;
    
    int a[15]={0,1,4,4,3,5};
    int b[15]={0,2,1,2,3,4};
    
    int main(){
    	rep(i,1,n)
    		q.push(node(a[i],b[i]));
        while(q.size()!=0){
        	printf("%d %d
    ",q.top().x,q.top().y);
    		q.pop();
    	}
        return 0;
    }
    
  • 相关阅读:
    luffy-短信接口频率限制,以及前端发送,和注册
    腾讯云短信开发
    luffy-登录注册页面
    vue之vue-cookies 获取、设置以及删除指定的cookies
    pycharm操作git
    luffy的前端主页
    vue路由跳转的方式
    django 中的Model继承
    跨域请求CORS详解
    vue:实现图书购物车
  • 原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11635456.html
Copyright © 2020-2023  润新知