最后的财产——模板大全

@

AC自动机

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
#define N 200007
int n,cnt,tot,go[N][26],fail[N],size[N],to[N];
char t[200007],s[2000007];
struct Edge{
	int to,next;
}e[N];
int head[N];
inline void add(int from,int to){
	e[++tot].to=to;
	e[tot].next=head[from];
	head[from]=tot;
}
void dfs(int u){
	for(ri i=head[u];i!=-1;i=e[i].next){
		int v=e[i].to;
		dfs(v);
		size[u]+=size[v];
	}
}
queue<int> q;
int main()
{
	scanf("%d",&n);
	for(ri i=1;i<=n;++i){
		scanf("%s",t);
		ri p=0,l=strlen(t);
		for(ri j=0;j<l;++j){
			int k=t[j]-'a';
			if(!go[p][k]) go[p][k]=++cnt;
			p=go[p][k];
		}
		to[i]=p;
	}
	for(ri i=0;i<26;++i)
		if(go[0][i])
			q.push(go[0][i]);
	while(q.size()){
		int p=q.front();
		q.pop();
		for(ri i=0;i<26;++i){
			if(!go[p][i]) go[p][i]=go[fail[p]][i];
			else{
				q.push(go[p][i]);
				fail[go[p][i]]=go[fail[p]][i];
			}
		}
	}
	scanf("%s",s);
	int len=strlen(s),p=0;
	for(ri i=0;i<len;++i){
		int j=s[i]-'a';
		p=go[p][j];
		++size[p];
	}
	for(ri i=0;i<=cnt;++i) head[i]=-1;
	for(ri i=1;i<=cnt;++i)
		add(fail[i],i);
	dfs(0);
	for(ri i=1;i<=n;++i)
		printf("%d
",size[to[i]]);
    return 0;
}

BSGS

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int SZ=1991107;
const ll M=998244353;
ll T,n,m,A,B,mod,ans;
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
struct hash_map{
    struct data{
        ll u;
        int v,nex;
    };
    data e[SZ<<1];
    int h[SZ],cnt;
    int hash(ll u){return u%SZ;}
    int& operator[](ll u){
	    int hu=hash(u);
	    for(int i=h[hu];i;i=e[i].nex)
	        if(e[i].u==u)
		  	      return e[i].v;
	    return e[++cnt]=(data){u,-1,h[hu]},h[hu]=cnt,e[cnt].v;
    }
    hash_map(){
        cnt=0;
        memset(h,0,sizeof(h));
    }
    void clear(){
        cnt=0;
        memset(h,0,sizeof(h));
    }
}mp;
inline ll fp(ll x,ll k){
	ll res=1;
	while(k){
		if(k&1) res=res*x%mod;
		k>>=1;
		x=x*x%mod;
	}
	return res;
}
int main()
{
	read(T);
	while(T--){
		ans=1e13;
		mp.clear();
		read(A);read(mod);
		if(A==0&&A==1){
			printf("1
");
			continue;
		}
		m=ceil(sqrt(mod));
		ll tmp1=fp(A,m),tmp2=1;
		for(int i=1;i<=m;++i){
			tmp2=tmp2*tmp1%mod;
			if(mp[tmp2]==-1) mp[tmp2]=i*m;
		}
		tmp1=A;tmp2=1;
		for(int j=0;j<=m;++j){
			if(mp[tmp2]!=-1&&mp[tmp2]-j>0) ans=min(ans,(ll)mp[tmp2]-(ll)j);
			tmp2=tmp2*tmp1%mod;
		}
		printf("%lld
",ans);
	}
    return 0;
}

KMP

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define ri register int
typedef long long ll;
const int N = 1000007;
char c1[N],c2[N];
int fail[N];

//inline void getfail( char s[] , int len ){
//	fail[ 0 ] = fail[ 1 ] = 0;
//	for( ri i = 1 ; i < len ; i++ ){
//		int t = fail[ i ];
//		while( t && s[ i ] != s[ t ] ) t = fail[ t ];
//		fail[ i + 1 ] = ( s[ t ] == s[ i ] ? t + 1 : 0 );
//	}
//}

//inline void match( char s1[] , char s2[] , int l1 , int l2 ){
//	int ans = 0,now = 0;//now指向模式串中下一个准备匹配的字符 
//	for( ri i = 0 ; i < l2 ; i++ ){
//		while( now && s2[ i ] != s1[ now ] ) now = fail[ now ];//失配 
//		if( s2[ i ] == s1[ now ] ) now++;
//		if( now == l1 ) printf( "%d
" , i - l1 + 2 ),now = fail[ now ];
//	}
//}//找在s2中,s1出现的次数,位置 

int main()
{
    scanf( "%s" , c2 );scanf( "%s" , c1 );
//    getfail( c1 , strlen( c1 ) );
//    match( c1 , c2 , strlen( c1 ) , strlen( c2 ) );
//    for( ri i = 1 ; i <= len ; i++ )
//      printf( "%d " , fail[ i ] )
    
      
    fail[ 0 ] = fail[ 1 ] = 0;int len = strlen( c1 );
    for( ri i = 1 ; i < len ; i++ ){
        int t = fail[ i ];
        while( t && c1[ i ] != c1[ t ] ) t = fail[ t ];
        fail[ i + 1 ] = ( c1[ t ] == c1[ i ] ? t + 1 : 0 );
    }
    
    
    register int now = 0,l1 = len,l2 = strlen( c2 );//now指向模式串中下一个准备匹配的字符 
    for( ri i = 0 ; i < l2 ; i++ ){
        while( now && c2[ i ] != c1[ now ] ) now = fail[ now ];//失配 
        if( c2[ i ] == c1[ now ] ) now++;
        if( now == l1 ) printf( "%d
" , i - l1 + 2 ),now = fail[ now ];
    }
    
    
    for( ri i = 1 ; i <= len ; i++ )
      printf( "%d " , fail[ i ] );
    return 0;
}

马拉车

#include<bits/stdc++.h>
using namespace std;
#define j (id<<1)-i 
const int N=11000007;
char t[N],s[N<<1];
int pal[N<<1];

inline int min(int a,int b){
    return a<b?a:b;
}

inline int max(int a ,int b){
    return a>b?a:b;
}

int main()
{
    scanf("%s",t);
    s[0]='+';
    int len=strlen(t);
    
    for(int i=1;i<(len<<1);i+=2){
        s[i]='#';
        s[i+1]=t[i>>1];
    }
    s[(len<<1)+1]='#';
    s[(len<<1)+2]='-';
    s[(len<<1)+3]='';
    
    int mx=0,id=0;
    len=(len<<1)+1;
    for(int i=1;i<=len;i++){
        if(mx>=i) pal[i]=min(mx-i+1,pal[j]);
        else pal[i]=1;
        while(s[i+pal[i]]==s[i-pal[i]]) pal[i]++;//暴力 
        if(i+pal[i]-1>mx){
            mx=i+pal[i]-1;
            id=i;
        }
    }
    
    int maxn=0;
    for(int i=1;i<=len;i++) maxn=max(maxn,pal[i]);
    printf("%d
",maxn-1);
    return 0;
}

最长公共子序列

#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int
const int N = 100005;
int n,len,a[N],ord[N],b[N],f[N];
template<class T>inline void read(T &res){static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;res *= flag;
}
int main()
{
    read( n );
    for( ri i = 1 ; i <= n ; i++ ) {read( a[ i ] );ord[ a[ i ] ] = i;}	
    for( ri i = 1 ; i <= n ; i++ ){read( b[ i ] );b[ i ] = ord[ b[ i ] ];}	
    memset( f , 0 , sizeof( f ) );f[ 1 ] = b[ 1 ];len = 1;
    for( ri i = 2 ; i <= n ; i++ ){
        if( b[ i ] > f[ len ] ){f[ ++len ] = b[ i ];continue;}
        int l = 1,r = len,mid;
        while( l <= r ){
            mid = ( l + r ) >> 1;
            if( f[ mid ] > b[ i ] ) r = mid - 1;
            else l = mid + 1;
        }f[ l ] = b[ i ];
    }printf( "%d" , len );
    return 0;
}

最小生成树

#include<bits/stdc++.h>
using namespace std;
struct Edge{
    int a,b,dis; 
}e[500000];//无向边,存边 
int father[100000];
int p,edge,tot=1,ans=0;

template<class T>inline void read(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}

int find( int x )
{
    if( father[ x ] != x )
      father[ x ]=find( father[ x ] );
    return father[ x ];
}

void unionn( int x , int y )
{
    father[ y ]=father[ x ];
}

bool cmp( Edge x , Edge y )
{
    return x.dis<y.dis;
}

void kruskal()
{
    sort( e + 1 , e + edge + 1 , cmp );
    for( int i = 1 ; i <= edge && tot <= p ; i ++ )
    {
        int r1=find( e[ i ].a ),r2=find( e[ i ].b );
        if( r1 == r2 )//判断两点是否已经在最小生成树中 
          continue;
        unionn( r1 , r2 );
        tot++;
        ans+=e[ i ].dis;
    }
    cout<<ans;
}

int main()
{
    cin>>p>>edge;
    for( int i = 1 ; i <= p ; i ++ )
      father[ i ]=i;//并查集初始化,自己叫自己爸爸
    for( int i = 1 ; i <= edge ; i ++ )
      read( e[ i ].a ),read( e[ i ].b ),read( e[ i ].dis ); 
    kruskal();
    return 0;
}

LCA

#include<cstdio>
#include<algorithm>
using namespace std;
#define oo 0x3f3f3f3f
#define ri register int
const int N = 500007;
typedef long long ll;
int n,m,s,tot,head[N],son[N],fa[N],top[N],size[N],deep[N];
struct Edge{
    int to,next;
}e[N<<1];
inline void add( int x , int y ){
    e[ ++tot ].to = y;
    e[ tot ].next = head[ x ];
    head[ x ] = tot;
}
template<class T>inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
    res *= flag;
}
void dfs1( int u ){
    size[ u ] = 1;
    for( ri i = head[ u ] ; i ; i = e[ i ].next ){
        int v = e[ i ].to;
        if( fa[ u ] == v ) continue;
        fa[ v ] = u;deep[ v ] = deep[ u ] + 1;
        dfs1( v );
        size[ u ] += size[ v ];
        if( !son[ u ] || size[ son[ u ] ] < size[ v ] )
          son[ u ] = v;
    }
}
void dfs2( int u , int tp ){
    top[ u ] = tp;
    if( son[ u ] ) dfs2( son[ u ] , tp );
    for( ri i = head[ u ] ; i ; i = e[ i ].next ){
        int v = e[ i ].to;
        if( v == son[ u ] || v == fa[ u ] ) continue;
        dfs2( v , v );
    }
}
int main()
{
    read( n );read( m );read( s );
    for( ri i = 1 ; i <= n - 1 ; i++ ){
    	int x,y;
        read( x );read( y );
        add( x , y );
        add( y , x );
    }tot = 0;deep[ s ] = 1;
    dfs1( s );
    dfs2( s , s );
    for( ri i = 1 ; i <= m ; i++ ){
    	int x,y;read( x );read( y );
    	while( top[ x ] != top[ y ] ){
        if( deep[ top[ x ] ] < deep[ top[ y ] ] ) swap( x , y );
            x = fa[ top[ x ] ];
        }
    	printf( "%d
" , deep[ x ] > deep[ y ] ? y : x );
    }
    return 0;
}

哈希

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
#define UL unsigned long long
#define BASE 1000000007
int n,ans = 0;
string s;
map<UL,int> judge;
void hash( string s ){
    UL cnt = 0;
    for( register int i = 0 ; i <= s.length() - 1 ; i++ )
      cnt = ( cnt + s[ i ] ) * BASE ;
    if( !judge[ cnt ] ) ans++;
    judge[ cnt ]++;
}
int main(){
    cin>>n;
    for( register int j = 1 ; j <= n ; j++ ){
        cin>>s;
        hash( s );
    }
    printf( "%d" , ans );
    return 0;
}

值域线段树

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define mid ((l+r)>>1)
const int N=500007;
int n,num,ndnum,a[N],b[N],ls[N],rs[N],sum[N]; 
template<class T> inline void read(T &res){
	T flag=1;static char ch;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
	res=ch-'0';
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-'0';
	res*=flag;
}
int build(int l,int r){
	int p=++ndnum;
	if(l==r) return p;
	ls[p]=build(l,mid);
	rs[p]=build(mid+1,r);
	return p;
}
void insert(int x,int p,int l,int r){
	if(l==r){
		++sum[p];
		return;
	}
	if(x<=b[mid])
		insert(x,ls[p],l,mid);
	else
		insert(x,rs[p],mid+1,r);
	sum[p]=sum[ls[p]]+sum[rs[p]];
}
int find(int rk,int p,int l,int r){
	if(l==r)
		return l;
	if(rk<=sum[ls[p]])
		return find(rk,ls[p],l,mid);
	return find(rk-sum[ls[p]],rs[p],mid+1,r);
}
int main()
{
	read(n);
	for(ri i=1;i<=n;++i) read(a[i]),b[i]=a[i];
	sort(b+1,b+n+1);
    num=unique(b+1,b+n+1)-b-1;
    build(1,num);
    insert(a[1],1,1,num);
    printf("%d
",a[1]);
    for(ri i=2;i<=n;++i){
    	insert(a[i],1,1,num);
    	if(i%2==1) printf("%d
",b[find((i+1)>>1,1,1,num)]);
	}
	return 0;
}

线性筛素数

#include<bits/stdc++.h>
using namespace std;
int zs[10000010],bc[2000010],tot=0;
void search(int n){
    for(int i=2;i<=n;i++){
        if(zs[i]==0)
        bc[++tot]=i;
        for(int j=1;j<=tot&&bc[j]*i<=n;j++){
            zs[bc[j]*i]=1;
            if(i%bc[j]==0)
            break;
        }
    }
}
int main(){
		freopen("group.out","w",stdout);
    int n,m,t;
    zs[0]=1;
    zs[1]=1;
    scanf("%d",&n);
    search(n);
//    scanf("%d",&m);
//    for(int i=1;i<=m;i++){
//    	scanf("%d",&t);
//    	bc[i]=t;
//    }
//    for(int i=1;i<=m;i++){
//     	if(zs[bc[i]]==0) printf("Yes
");
//     	else printf("No
");
//    }
	for(int i=1;i<=2000000;++i) printf("%d ",bc[i]);
    return 0;
}

线性筛逆元

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
long long n,p,inv[3000007];
int main()
{
	cin>>n>>p;
 	inv[1]=1;
 	for(int i=2;i<=n;++i)
 		inv[i]=(p-p/i)*inv[p%i]%p;
 	for(int i=1;i<=n;++i) printf("%lld
",inv[i]);
    return 0;
}

线段树

#include<cstdio>
using namespace std;
#define N 100007
typedef long long ll;
int n,m,tot=0,p;
ll a[N];
struct Node{
    ll sum,flag,cflag;
    Node *ls,*rs;
    Node(){
        sum = flag = 0;
        cflag = 1;
        ls = rs = NULL;
    }
    inline void pushdown( int l , int r ){
        int mid = ( l + r ) >> 1;
        ls->sum = ( ls->sum * cflag % p + flag * ( mid - l + 1 ) % p ) % p;
        rs->sum = ( rs->sum * cflag % p + flag * ( r - mid ) % p ) % p;
        ls->flag = ( ls->flag * cflag + flag ) % p;
        rs->flag = ( rs->flag * cflag + flag ) % p;
        ls->cflag = cflag * ls->cflag % p;
        rs->cflag = cflag * rs->cflag % p;
        flag = 0;cflag = 1;
    }
    inline void update(){
        sum = ( ls->sum + rs->sum ) %p;
    }
}tree[N<<1],*q = tree,*root;

Node *build( int l , int r ){
    Node *nd = ++q;
    if( l == r ){
        nd->sum = a[ l ] % p;
        return nd;
    }
    int mid = ( l + r )>>1;
    nd->ls = build( l , mid );
    nd->rs = build( mid + 1 , r );
    nd->update();
    return nd;
}

ll query( int l , int r , int x , int y , Node *nd ){
    if( x <= l && y >= r )
      return nd->sum;
    if( l > y || r < x )
      return 0;
    nd->pushdown( l , r );
    int mid = ( l + r ) >> 1;
    return query( l , mid , x , y , nd->ls ) + query( mid + 1 , r , x , y , nd->rs );
    
}

void modify( int l , int r , int x , int y , int add , Node *nd )
{
    if( x <= l && r <= y ) {
        nd->sum = ( nd->sum + ( r - l + 1 ) * add ) % p;
        nd->flag = ( nd->flag + add ) %p;
        return;
    }
    int mid = ( l + r ) >> 1;
    nd->pushdown( l , r );
    if( x <= mid )
        modify( l , mid , x , y , add , nd->ls );
    if( y > mid )
        modify( mid + 1 , r , x , y , add , nd->rs );
    nd->update();
}

void cmodify( int l , int r , int x , int y , int c , Node *nd ){
    if( x <= l && r <= y ) {
        nd->sum = nd->sum * c % p;
        nd->flag = nd->flag * c % p;
        nd->cflag = nd->cflag * c % p;
        return;
    }
    int mid = ( l + r ) >> 1;
    nd->pushdown( l , r );
    if( x <= mid )
        cmodify( l , mid , x , y , c , nd->ls );
    if( y > mid )
        cmodify( mid + 1 , r , x , y , c , nd->rs );
    nd->update();
}

int main()
{
    scanf( "%d %d %d" , &n , &m , &p );
    for( register int i = 1 ; i <= n ; i ++ )
      scanf( "%lld" , &a[ i ] );
    root=build( 1 , n );
    for( register int i = 1 ; i <= m ; i ++ ){
        int f;
        scanf( "%d" , &f );
        switch( f ){
        	case 2:{
        		int x,y,add;
        		scanf( "%d %d %d" , &x , &y , &add );
        		modify( 1 , n , x , y , add , root );
        		break;
        	}
        	case 1:{
        		int x,y,add;
        		scanf( "%d %d %d" , &x , &y , &add );
        		cmodify( 1 , n , x , y , add , root );
        		break;
        	}
        	case 3:{
        		int x,y;
        		scanf( "%d %d" , &x , &y );
        		printf( "%lld
" , query( 1 , n , x , y , root ) % p );
        		break;
        	}
        }
    }
    return 0;
}

舞蹈链

#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define oo 0x3f3f3f3f
#define N 253510
#define XN 505
#define head 0
typedef long long ll;
int n,m,cnt;
int left[ N ] = {},right[ N ] = {},up[ N ] = {},down[ N ] = {};
int col[ N ] = {},row[ N ] = {};
int ans[ XN ] = {};
int col_cnt[ XN ] = {};
int row_first[ XN ] = {};

template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
      res = res * 10 + ch - 48;
    res *= flag;
}

inline void chushihua(){
    memset( row_first , -1 , sizeof( row_first ) );
    for( int i = 0 ; i <= m ; i++ ){
        up[ i ] = down[ i ] = i;
        right[ i ] = i + 1;
        left[ i ] = i - 1;
    }
    left[ head ] = m;right[ m ] = head;
    cnt = m;
}

inline void charu( int hang , int lie ){
    col_cnt[ lie ]++;
    row[ ++cnt ] = hang;col[ cnt ] = lie;
    up[ cnt ] = lie;
    down[ cnt ] = down[ lie ];
    up[ down[ lie ] ] = cnt;
    down[ lie ] = cnt;
    if( row_first[ hang ] == -1 ) row_first[ hang ] = right[ cnt ] = left[ cnt ] = cnt;
    else{
        right[ cnt ] = row_first[ hang ];
        left[ cnt ] = left[ row_first[ hang ] ];
        right[ left[ row_first[ hang ] ] ] = cnt;
        left[ row_first[ hang ] ] = cnt;
    }
}

inline void shanchu( int l ){
    right[ left[ l ] ] = right[ l ];left[ right[ l ] ] = left[ l ];
    for( int i = down[ l ] ; i != l ; i = down[ i ] )
      for( int j = right[ i ] ;  j != i ; j = right[ j ] ){
      	  down[ up[ j ] ] = down[ j ];
          up[ down[ j ] ] = up[ j ];
          col_cnt[ col[ j ] ]--;
      }
}

inline void huifu(int l){
    for( int i = up[ l ] ; i != l ; i = up[ i ] )
      for( int j = left[ i ] ; j != i ; j = left[ j ] ){
      	  down[ up[ j ] ] = up[ down[ j ] ] = j;
          col_cnt[ col[ j ] ]++;
      }
    left[ right[ l ] ] = right[ left[ l ] ] = l;
}

bool Dance( int piece ){
    if( right[ head ] == head ){
    	for( int i = 0; i < piece ; ++i )
        printf( "%d
" , ans[ i ] );
    	return true;
    }
    int l = right[ head ];
    for( register int i = right[ head ] ; i != head ; i = right[ i ] )
      if( col_cnt[ i ] < col_cnt[ l ] ) l = i;
    shanchu( l );
    for( register int i = down[ l ] ; i != l ; i = down[ i ] ){
        ans[ piece ] = row[ i ];
        for( register int j = right[ i ] ; j != i ; j = right[ j ] )
          shanchu( col[ j ] );
        if( Dance( piece + 1 ) ) return true;
        for( register int j = left[ i ] ; j != i ; j = left[ j ] ) 
          huifu( col[ j ] );
    }
    huifu( l );
    return false;
}

int main()
{
    read( n ),read( m );
    chushihua();
    for( register int i = 1 ; i <= n ; i++ )
      for( register int j = 1 ; j <= m ; j++ ){
      	  int x;read( x );
      	  if( x == 1 ) charu( i , j );
      }
    if( !Dance( 0 ) ) printf( "No Solution!
" );
    return 0;
}

文艺平衡树

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
#define INF 200000
const int N=200001;
int a[N];
int n,m;
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
	res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48;
	res*=flag;
}
class Splay{
	public: 
	int root=0,ndnum=0,son[N][2],fa[N],size[N],cnt[N],val[N];
	bool tag[N];
	inline void update(int p){
		size[p]=size[son[p][0]]+size[son[p][1]]+cnt[p];
	}
	inline void pushdown(int p){
		if(tag[p]){
			if(son[p][0]) tag[son[p][0]]^=1;
			if(son[p][1]) tag[son[p][1]]^=1;
			swap(son[p][0],son[p][1]);
			tag[p]^=1;
		}
	}
	inline bool check(int p){
		return p==son[fa[p]][1];
	}
	inline void rotate(int p){
		int f=fa[p],ff=fa[f],k=check(p),kk=check(f),nd=son[p][k^1];
		son[ff][kk]=p;fa[p]=ff;
		son[p][k^1]=f;fa[f]=p;
		son[f][k]=nd;fa[nd]=f;
		update(f);update(p);
	}
	inline void splay(int p,int goal){
		if(p==goal) return; 
		while(fa[p]!=goal){
			int f=fa[p],ff=fa[f];
			if(ff!=goal){
				if(check(p)==check(f))
					rotate(f);
				else rotate(p);
			}
			rotate(p);
		}
		if(goal==0) root=p;
	}
    inline int search(int rk){
    	int p=root;
    	while(1){
    		pushdown(p);
    		if(son[p][0]&&rk<=size[son[p][0]]) p=son[p][0];
    		else if(rk>size[son[p][0]]+cnt[p]){
    			rk-=size[son[p][0]]+cnt[p];
    			p=son[p][1];
			}
			else	return p;
		}
	}
	inline void insert(int x){
		int f=0,cur=root;
		while(cur&&x!=val[cur]){
			f=cur;
			cur=son[cur][x>val[cur]];
		}
		if(cur) ++cnt[cur];
		else{
			cur=++ndnum;
			fa[cur]=f;
			son[cur][0]=son[cur][1]=0;
			size[cur]=cnt[cur]=1;
			val[cur]=x;
			if(f) son[f][x>val[f]]=cur;
		}
		splay(cur,0);
	}
	inline void reverse(int l,int r){
		l=search(l);r=search(r+2);
		splay(l,0);splay(r,l);
		tag[son[r][0]]^=1;
	}
	inline void bianli(int p){
		pushdown(p);
		if(son[p][0]) bianli(son[p][0]);
		if(val[p]<n+2&&val[p]>1)
			printf("%d ",val[p]-1);
		if(son[p][1]) bianli(son[p][1]);
	}
}Tree;
int main()
{
	read(n);read(m);
	for(ri i=1;i<=n+2;++i) Tree.insert(i);
	for(ri i=1;i<=m;++i){
		int l,r;
		read(l);read(r);
		Tree.reverse(l,r);
	}
	Tree.bianli(Tree.root);
    return 0;
}

最大流

//dinic算法 
#include<bits/stdc++.h>
using namespace std;
#define oo 0x3f3f3f3f
#define N 150005
#define M 15005
#define ri register int 
typedef long long ll;
int timer = 0,n,m,s,t,tot = -1,head[M],dis[M],vis[M],cur[M]; 
struct Edge{
    int to,next,w;
}e[N<<1];

template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
      res = res * 10 + ch - 48;
    res *= flag;
}

inline void add( int from , int to , int w ){
    e[ ++tot ].to = to;
    e[ tot ].w = w;
    e[ tot ].next = head[ from ];
    head[ from ] = tot;
}

int dfs( int x , int lim ){
    if( x == t ) return lim;
    int ans = 0;
    for( ri i = cur[ x ] ; i != -1 ; i = e[ i ].next ){
    	cur[ x ] = i;
    	if( e[ i ].w && dis[ e[ i ].to ] == dis[ x ] + 1 ){
      	    int y = dfs( e[ i ].to , min( e[ i ].w , lim ) );
      	    if( y ){
      	  	     e[ i ].w -= y;e[ i^1 ].w += y;
      	  	    ans += y;lim -= y;
      	  	    if( !lim ) return ans;
      	    }
        }
    }
      
    return ans;
}

inline bool bfs(){
    timer++;
    queue<int> q;
    dis[ s ] = 0;vis[ s ] = timer;
    q.push( s );
    while( !q.empty() ){
        int x = q.front();q.pop();
        for( ri i = head[ x ] ; i != -1 ; i = e[ i ].next ){
            int v = e[ i ].to;
            if( e[ i ].w == 0 ) continue;
            if( vis[ v ] != timer ){
                vis[ v ] = timer;
                dis[ v ] = dis[ x ] + 1;
                q.push( v ); 
            }
        }
    }
    return vis[ t ] == timer;
}//判断是否可以增广 

int dinic(){
    int ans = 0;
    while( bfs() ){
    	for( ri i = 1 ; i <= n ; i++ ) cur[ i ] = head[ i ];
        ans += dfs( s , 2147483647 );	
    }
    return ans;
}

int main()
{
    read( n );read( m );read( s );read( t );
    for( ri i = 1 ; i <= n ; i++ ) head[ i ] = -1;//初始化
    for( ri i = 1 ; i <= m ; i++ ){
    	int x,y,z;read( x );read( y );read( z );
    	add( x , y , z );add( y , x , 0 );//建边的同时要建一条虚拟边 
    }
    cout<<dinic();
    return 0;
}

缩点

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
using namespace std;
#define oo 0x3f3f3f3f
#define N 10010
typedef long long ll;
int ans = 0,n,m,tot = 0,cnt= 0,vf[ N ],low[ N ],w[ N ],head[ N ],nhead[ N ],bel[ N ],np[ N ],g[ N ];
bool est[ N ];
stack<int> q;

struct Edge{
    int to,next,from;
}e[ N * 10 ],ne[ N * 10 ];

template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
      res = res * 10 + ch - 48;
    res *= flag;
}

inline void add( int from , int to ){
    e[ ++tot ].to = to;
    e[ tot ].next = head[ from ];
    e[ tot ].from = from;
    head[ from ] = tot;
}

inline void nadd( int from , int to ){
    ne[ ++tot ].to = to;
    ne[ tot ].next = nhead[ from ];
    ne[ tot ].from = from;
    nhead[ from ] = tot;
}

void tarjan( int x ){
    q.push( x );vf[ x ] = low[ x ] = ++cnt;est[ x ] = true;
    for( register int i = head[ x ] ; i ; i = e[ i ].next ){
    	int v = e[ i ].to;
    	if( !vf[ v ] ){tarjan( v );low[ x ] = min( low[ x ] , low[ v ] );}//没被访问 
    	else if( est[ v ] ) low[ x ] = min( low[ x  ] , vf[ v ] ); //在栈中
    }
    if( vf[ x ] == low[ x ] ){
    	int v;tot++;
    	while( v = q.top() ){
    		bel[ v ] = tot;np[ tot ] += w[ v ];//缩点 
//    		printf( "%d " , v );
    		est[ v ] = false;q.pop();
    		if( v == x ) break;
    	}
//    	printf( "
" );
    }//弹栈 
}

void search( int x ){
    if( g[ x ] ) return;
    g[ x ] = np[ x ];
    int maxn = 0;
    for( int i = nhead[ x ] ; i ; i = ne[ i ].next ){
        if( !g[ ne[ i ].to ] ) search( ne[ i ].to );
        maxn = max( maxn , g[ ne[ i ].to ] );
    }
    g[ x ] += maxn;
}//记忆化搜索 

int main()
{
    read( n );read( m );
    for( register int i = 1 ; i <= n ; i++ ) read( w[ i ] );
    //读入点权 
    for( register int i = 1 ; i <= m ; i++ ){
        int x,y;read( x );read( y );
        add( x , y );
    }tot = 0;//建边
    for( register int i = 1 ; i <= n ; i++ )
      if( !vf[ i ] ) tarjan( i );//tarjan找强连通分量 
    for( register int i = 1 ; i <= m ; i++ ){//枚举每条边 
        int x = e[ i ].from,y = e[ i ].to;
        if( bel[ x ] == bel[ y ] ) continue;
        nadd( bel[ x ] , bel[ y ] );//建新图
    }
//	for( register int i = 1 ; i <= tot ; i++ )
//	  printf( "%d " , np[ i ] );
    for( register int i = 1 ; i <= tot ; i++ )
      if( !g[ i ] ){
      	  search( i );
      	  ans = max( ans , g[ i ] );
      }
    printf( "%d" , ans );
    return 0;
}

树状数组

#include<bits/stdc++.h>
using namespace std;
int a[500005];
int c[500005];
int ans[500005]; 
int num,x,tot=0;

int lowbit( int x )//求一个数在二进制表示下最低位的1以及它后面的0构成的数值 
{
    return x & ( - x );//与运算 
}

void update( int ord , int s )//修改
{
    a[ ord ]+=s;
    while( ord <= num )
    {
        c[ ord ]+=s;
        ord+=lowbit( ord );
    }
}

int sum( int k )//查询前缀和 
{
    int anss=0;
    while( k )
    {
        anss+=c[ k ];
        k-=lowbit( k );
    } 
    return anss;
}

int main()
{
    scanf( "%d%d" , &num , &x );
    for( int i = 1 ; i <= num ; i ++ )
    {
        scanf( "%d" , &a[ i ] );
        update( i , a[ i ] ); 
    }
    for( int i = 1 ; i <= x ; i ++ )
    {
        int k;
        scanf( "%d" , &k );
        if( k == 1 )//修改
        {
            int ord,s;
            scanf( "%d%d" , &ord , &s );
            update( ord , s );
            continue;
        }
        //查询
        int l,r;
        scanf( "%d%d" , &l , &r );
        ans[ ++ tot ]=sum( r )-sum( l - 1 ); 
    }
    for( int i = 1 ; i <= tot - 1 ; i ++ )
      printf( "%d
" , ans[ i ] );
    printf( "%d" , ans[ tot ] );
    return 0;
}

树剖

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
#define N 500005
#define ri register int
int tot=0,n,m,rt,md;
int fa[N],deep[N],head[N],size[N],son[N],id[N],w[N],nw[N],top[N];
struct EDGE{
    int to,next;
}e[N];
inline void add(int from,int to){
    e[++tot].to=to;
    e[tot].next=head[from];
    head[from]=tot;
}
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
struct NODE{
    ll sum,flag;
    NODE *ls,*rs;
    NODE(){
        sum=flag=0;
        ls=rs=NULL;
    }
    inline void pushdown(int l,int r){
        if(flag){
            int midd=(l+r)>>1;
            ls->flag+=flag;
            rs->flag+=flag;
            ls->sum+=flag*(midd-l+1);
            rs->sum+=flag*(r-midd);
            flag=0;
        }
    }
    inline void update(){
        sum=ls->sum+rs->sum;
    }
}tree[N*2+5],*p=tree,*root;
NODE *build(int l,int r){
    NODE *nd=++p;
    if(l==r){
        nd->sum=nw[l];
        return nd;
    }
    int mid=(l+r)>>1;
    nd->ls=build(l,mid);
    nd->rs=build(mid+1,r);
    nd->update();
    return nd;
}
ll sum(int l,int r,int x,int y,NODE *nd){
    if(x<=l&&r<=y) return nd->sum;
    nd->pushdown(l,r);
    int mid=(l+r)>>1;
    ll res=0;
    if(x<=mid) res+=sum(l,mid,x,y,nd->ls);
    if(y>=mid+1) res+=sum(mid+1,r,x,y,nd->rs);
    return res;
}
void modify(int l,int r,int x,int y,ll add,NODE *nd){
    if(x<=l&&r<=y){
        nd->sum+=(r-l+1)*add;
        nd->flag+=add;
        return;
    }
    int mid=(l+r)>>1;
    nd->pushdown(l,r);
    if(x<=mid) modify(l,mid,x,y,add,nd->ls);
    if(y>mid) modify(mid+1,r,x,y,add,nd->rs);
    nd->update();
}
void dfs1(int p){
    size[p]=1;
    deep[p]=deep[fa[p]]+1;
    for(int i=head[p];i;i=e[i].next){
        int k=e[i].to;
        if(k==fa[p]) continue;
        fa[k]=p;
        dfs1(k);
        size[p]+=size[k];
        if(size[son[p]]<size[k]||!son[p]) son[p]=k;
    }
}//第一次预处理,找到各个点的深度,size,重儿子,爸爸 
void dfs2(int p,int tp){//第二次预处理,找出重链,dfs序 
    id[p]=++tot;//每个点在dfs序里的位置
    nw[tot]=w[p];
    top[p]=tp;
    if(son[p]) dfs2(son[p],tp);//重链
    for(int i=head[p];i;i=e[i].next){
        int k=e[i].to;
        if(k==fa[p]||k==son[p]) continue;
        dfs2(k,k);//轻链
    }
}
inline void ope1(int x,int y,ll add){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);//注意是deep[top[x]]!
        modify(1,n,id[top[x]],id[x],add,root);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    modify(1,n,id[x],id[y],add,root);
}
inline ll ope2(int x,int y){
    ll res=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        res+=sum(1,n,id[top[x]],id[x],root);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    res+=sum(1,n,id[x],id[y],root);
    return res;
}
inline void ope3(int x,int add){
    modify(1,n,id[x],id[x]+size[x]-1,add,root);
}
inline ll ope4(int x){
    return sum(1,n,id[x],id[x]+size[x]-1,root);
}
int main()
{
    cin>>n>>m>>rt>>md;
    for(ri i=1;i<=n;i++)
      read(w[i]);//点权 
    for(ri i=1;i<=n-1;i++){
        int x,y;
        read(x),read(y);
        add(x,y);
        add(y,x);
    }
    dfs1(rt),tot=0;
    dfs2(rt,rt);
    root=build(1,n);
    for(ri i=1;i<=m;i++){
        int f;
        read(f);
        switch(f){
            case 1:{//链修改
                int x,y;
                ll add;
                read(x),read(y),read(add);
                ope1(x,y,add); 
                break;
            }
            case 2:{//链查询 
                int x,y;
                read(x),read(y);
                printf("%lld
",ope2(x,y)%md);
                break;
            }
            case 3:{//子树修改 
                int x;
                ll add;
                read(x),read(add);
                ope3(x,add);
                break;
            }
            case 4:{//子树查询 
                int x;
                read(x);
                printf("%lld
",ope4(x)%md);
                break;
            }
        }
    }
    return 0;
}

三维偏序

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
const int N=300007;
int n,k,tot,sum[N],to[N],Ans[N],tong[N];
class Node{
	public:
	int a,b,c,t,cnt,ans;
}node[N],po[N],P[N];
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
	res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48;
	res*=flag;
}
inline int lowbit(int x){
	return x&(-x);
}
inline void update(int sta,int x){
	while(sta<=k){
		sum[sta]+=x;
		sta+=lowbit(sta);
	}
}
inline int query(int sta){
	int res=0;
	while(sta>0){
		res+=sum[sta];
		sta-=lowbit(sta);
	}
	return res;
}
inline bool cmp(Node x,Node y){
	if(x.a==y.a&&x.b==y.b) return x.c<y.c;
	if(x.a==y.a) return x.b<y.b;
	return x.a<y.a;
}
inline bool check(Node x,Node y){
	return (x.a==y.a&&x.b==y.b&&x.c==y.c);
}
inline bool cmp1(Node x,Node y){
	return x.t<y.t;
} 
inline void cdq(int l,int r){
	if(l==r) return;
	int mid=(l+r)>>1;
	cdq(l,mid);
	cdq(mid+1,r);
	int i=l,j=mid+1,k=l;
	while(i<=mid&&j<=r){
		if(po[i].b<=po[j].b){
			update(po[i].c,po[i].cnt);
			P[k++]=po[i++];
		}
		else{
			po[j].ans+=query(po[j].c);
			P[k++]=po[j++];
		}
	}
	while(i<=mid){
		update(po[i].c,po[i].cnt);
		P[k++]=po[i++];
	}
	while(j<=r){
		po[j].ans+=query(po[j].c);
		P[k++]=po[j++];
	}
	for(ri t=l;t<=mid;++t) update(po[t].c,-po[t].cnt);
 	for(ri t=l;t<=r;++t) po[t]=P[t];
}
int main()
{
	read(n);read(k);
	for(ri i=1;i<=n;++i){
		read(node[i].a);
		read(node[i].b);
		read(node[i].c);
		node[i].t=i;
	}
	sort(node+1,node+n+1,cmp);
	po[++tot]=node[1];
	po[tot].t=tot;
	po[tot].cnt=1;
	to[1]=1;
	for(ri i=2;i<=n;++i){
		if(check(po[tot],node[i])) ++po[tot].cnt;
		else{
			po[++tot]=node[i];
			po[tot].t=tot;
			po[tot].cnt=1;
		}
		to[i]=tot;
	}
	cdq(1,tot);
	sort(po+1,po+tot+1,cmp1);
	for(ri i=1;i<=n;++i) Ans[node[i].t]=po[to[i]].ans+po[to[i]].cnt-1;
	for(ri i=1;i<=n;++i) ++tong[Ans[i]];
	for(ri i=0;i<n;++i) printf("%d
",tong[i]);
    return 0;
}

卢卡斯定理

#include<bits/stdc++.h>
using namespace std;
#define ri register int 
#define ll long long 
const int N = 300007;
ll T,m,n,p;
ll M[N];

void exgcd( ll a , ll b , ll &x , ll &y ){
     if( !b ){
         x = 1;
         y = 0;
         return;
     }
     ll x1,y1;
     exgcd( b , a % b , x1 , y1 );
     x = y1;
     y = x1 - y1 * ( a / b );
}
inline ll inv( ll a ){
    ll xx,yy;
    exgcd( a , p , xx , yy );
    xx = ( xx % p + p ) % p;
    return xx;
}

inline ll C( ll n , ll m ){
   return m > n ?  0 : M[ n ] * inv( M[ m ] ) % p * inv( M[ n - m ] ) % p;
}

ll lucas( ll n , ll m ){
    return m ? lucas( n / p , m / p ) * C( n % p , m % p ) % p : 1LL;
}

int main()
{
    scanf( "%lld" , &T );
    while( T-- ){
    	scanf( "%lld%lld%lld" , &n , &m , &p );
    	M[ 0 ] = 1;
    	for( register ll i = 1 ; i <= n + m + 7 ; ++i )
    	  M[ i ] = M[ i - 1 ] * i % p;
    	printf( "%lld
" , lucas( n + m , m ) );
    }
    return 0;
}

excrt

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,aa,bb;
ll x=0,y,lcm=1,t,gcd;
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1;
	res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48;
	res*=flag;
}
ll slow_mul(ll x,ll k,ll mod){
	if(x<=0&&k<=0) x=-x,k=-k;
	else if(k<0) swap(x,k);
	ll ans=0;x%=mod;
	while(k){
		if(k&1) ans=(ans+x)%mod;
		k>>=1;
		x=x*2%mod;
	}
	return ans;
}
ll exgcd(ll &x,ll &y,ll a,ll b){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	ll g=exgcd(x,y,b,a%b);
	ll c=y;
	y=x-a/b*y;
	x=c;
	return g;
}
int main()
{
	read(n);
	for(int i=1;i<=n;++i){
		read(aa);read(bb);
		gcd=exgcd(t,y,lcm,aa);
		ll l=lcm/gcd*aa;
		ll m=l/lcm;
		t=slow_mul((bb-x)/gcd,t,m);
		t=(t%m+m)%m;
		x=x+t*lcm;
		lcm=l;
		x=(x%lcm+lcm)%lcm;
	}
	printf("%lld
",x);
    return 0;
}

快排

#include<bits/stdc++.h>
using namespace std;
int n,x,heap_size=0;
int heap[3000000];
void put(int d)
{
    int now,next;
    heap[++heap_size]=d;
    now=heap_size;
    while(now>1)
    {
        next=now/2;
        if(heap[now]<heap[next])
        swap(heap[now],heap[next]);
        now=next;
    } 
}
int get()
{
    int res=heap[1];
    int now=1,next;
    heap[1]=heap[heap_size--];
    while(now*2<=heap_size)
    {
        next=2*now;
        if(next<heap_size&&heap[next+1]<heap[next])
        next++;
        if(heap[now]<=heap[next])
        return res;
        else
        {
            swap(heap[now],heap[next]);
            now=next;
        }
    }
    return res;
}
int main()
{
    //freopen("btree.in","r",stdin);
    //freopen("btree.out","w",stdout);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        put(x);
    }
    for(int i=1;i<=n;i++)
    cout<<get()<<" ";
    return 0;
} 

快速幂

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int 
#define ll long long 
ll b,t,h,P;
char c[ 100007 ];
ll TenthPow( ll a ){
    ll ans = 1,s = a;
    while( t >= 0 ){
        ll cnt = c[ t ] - '0',cur = s;
        for( ri i = 1 ; i <= cnt ; ++i )
          ans = ans * s % P;
        for( ri i = 1 ; i < 10 ; ++i )
          cur = cur * s % P;
        s = cur;
        ans %= P;
        --t;
    }
    return ans;
}
int main()
{
    cin>>b>>c>>P;
    t = strlen( c );--t;
    cout<<b<<"^"<<c<<" mod "<<P<<"="<<TenthPow( b );
    return 0;
}

主席树

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
using namespace std;
#define oo 0x3f3f3f3f
#define mid ( ( l + r ) >> 1 )
#define ri register int
const int N = 200007,M = 4000000; 
typedef long long ll;
int n,m,tot,num,pos,a[N],b[N],root[N],ls[M],rs[M],sum[M];

template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
    res *= flag;
}

inline void copy( int a , int b ){
    ls[ a ] = ls[ b ];
    rs[ a ] = rs[ b ];
    sum[ a ] = sum[ b ] + 1;//由于插入了一个结点,所以要加1 
}

int build( int l , int r ){
    int s = ++tot;
    if( l == r ) return s;
    ls[ s ] = build( l , mid );
    rs[ s ] = build( mid + 1 , r );
    return s;
}

int modify( int l , int r , int s ){
    int t = ++tot;
    copy( t , s );
    if( l == r ) return t;
    if( pos <= mid ) ls[ t ] = modify( l , mid , ls[ t ] );
    else rs[ t ] = modify( mid + 1 , r , rs[ t ] );
    return t;
}

int query( int l , int r , int s , int ss , int k ){
    int res = sum[ ls[ ss ] ] - sum[ ls[ s ] ];
    if( l == r ) return b[ l ];
    if( res >= k ) return query( l , mid , ls[ s ] , ls[ ss ] , k );
    //多了,就递归到左子树去找k个 
    else return query( mid + 1 , r , rs[ s ] , rs[ ss ] , k - res );
    //少了,就递归到右子树去再找k-res个 
}

int main()
{
    read( n );read( m );
    for( ri i = 1 ; i <= n ; i++ ){
    	read( a[ i ] );
    	b[ i ] = a[ i ];
    }
    sort( b + 1 , b + n + 1 );
    num = unique( b + 1 , b + n + 1 ) - b - 1;//最终返回了去重后的元素个数 
    root[ 0 ] = build( 1 , num );
    for( ri i = 1 ; i <= n ; i++ ){
    	int l = 1,r = num;
    	while( l <= r ){
    		if( a[ i ] <= b[ mid ] ) r = mid - 1;
    		else l = mid + 1;
    	}pos = l;
    	root[ i ] = modify( 1 , num , root[ i - 1 ] );
    }
    for( ri i = 1 ; i <= m ; i++ ){
    	int l,r,k;read( l );read( r );read( k );
    	printf( "%d
" , query( 1 , num , root[ l - 1 ] , root[ r ] , k ) );
    }
    return 0;
}

可持久化线段树

#include<cstdio>
using namespace std;
#define ri register int 
#define mid ( ( l + r ) >> 1 ) 
const int N = 20000007,M = 1000007;
typedef long long ll;
int tot,ls[N],rs[N],root[M],a[M];
ll sum[N];
template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
    res *= flag;
}
inline void update( int s ){
    sum[ s ] = sum[ ls[ s ] ] + sum[ rs[ s ] ];
}
inline void copy( int a , int b ){
    ls[ a ] = ls[ b ];
    rs[ a ] = rs[ b ];
    sum[ a ] = sum[ b ];
}
inline int modify( int s , int l , int r , int ord , int x ){
    int t = ++tot;
    copy( t , s );
    if( l == r ){
        sum[ t ] = x;
        return t;
    }
    if( ord <= mid ) ls[ t ] = modify( ls[ t ] , l , mid , ord , x );
    else rs[ t ] = modify( rs[ t ] , mid + 1 , r , ord , x );
    update( t );
    return t;
}
inline int query( int s , int l , int r , int pos ){
    if( l == r ){
        return sum[ s ]; 
    }
    if( pos <= mid ) return query( ls[ s ] , l , mid , pos );
    else return query( rs[ s ] , mid + 1 , r , pos );
}
void build( int s , int l , int r ){
    if( l == r ) {
        sum[ s ] = a[ l ];
        return;
    }
    build( ls[ s ] = ++tot , l , mid );
    build( rs[ s ] = ++tot , mid + 1 , r );
    update( s );
}
int main()
{
    int n,m;read( n );read( m );
    for( ri i = 1 ; i <= n ; i++ ) read( a[ i ] );
    build( root[ 0 ] = ++tot , 1 , n );
    for( ri i = 1 ; i <= m ; i++ ){
    	int typ,NUM,pos;read( NUM );read( typ );read( pos );
    	if( typ == 1 ){
    		int val;read( val );
    		root[ i ] = modify( root[ NUM ] , 1 , n , pos , val );
    	}
    	else{
    		root[ i ] = root[ NUM ];
    		printf( "%d
" , query( root[ NUM ] , 1 , n , pos ) );
    	}
    }
    return 0;
}

矩阵快速幂

#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int
typedef long long ll;
const int N = 107;
const ll P = 1000000007;
ll n,k;
struct Matrix{
    ll A[N][N];
    inline void refresh(){
        for( ri i = 1 ; i <= n ; ++i )
          A[ i ][ i ] = 1;
    }//建立单位矩阵 
}cur,net;

Matrix operator *( const Matrix &x , const Matrix &y ){
    Matrix z;
    memset( z.A , 0 , sizeof( z.A ) );
    for( int i = 1 ; i <= n ; ++i )
      for( int j = 1 ; j <= n ; ++j )
        for( int k = 1 ; k <= n ; ++k )
          z.A[ i ][ j ] = ( z.A[ i ][ j ] + x.A[ i ][ k ] * y.A[ k ][ j ] % P ) % P;
    return z;
}

inline Matrix qpow( Matrix a , ll k ){
    Matrix ans;
    ans.refresh();
    while( k ){
        if( k & 1 )
          ans = ans * a;
        a = a * a;
        k = k >> 1;
    }
    return ans;
}

template<class T>inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
    res *= flag;
}

int main()
{
    read( n );
    read( k );
    for( ri i = 1 ; i <= n ; ++i )
      for( ri j = 1 ; j <= n ; ++j )
        read( cur.A[ i ][ j ] );
    net = qpow( cur , k );
    for( ri i = 1 ; i <= n ; ++i ){
        for( ri j = 1 ; j <= n ; ++j )
          printf( "%lld " , net.A[ i ][ j ] );
        putchar( '
' );	
    }
    return 0;
}

后缀自动机

#include<bits/stdc++.h>
using namespace std;
#define ri register int
#define ll long long
const int N=2000007;
int root=1,len,ndnum=1,last=1;
char s[N>>1];
struct Node{
	int par,go[26];
	ll len;
}node[N];
struct Edge{
	int to,next;
}e[N];
int tot,head[N];
ll f[N],ans;
template<class T>inline void read(T &res){
	static char go;T flag=1;
	while((go=getchar())<'0'||go>'9') if(go=='-') flag=-1;
	res=go-48;
	while((go=getchar())>='0'&&go<='9') res=(res<<1)+(res<<3)+go-48;
	res*=flag;
}
inline int New(){
	int p=++ndnum;
	memset(node[p].go,0,sizeof(node[p].go));
	return p;
}
inline void Add(int w){
	int x=New(),tmp=last;
	f[x]=1;
	node[x].len=node[last].len+1;
	while(tmp&&!node[tmp].go[w]){
		node[tmp].go[w]=x;
		tmp=node[tmp].par;
	}
	if(!tmp) node[x].par=root;
	else{
		int B=node[tmp].go[w];
		if(node[B].len==node[tmp].len+1) node[x].par=B;
		else{
			int nB=New();
			node[nB]=node[B];
			node[nB].len=node[tmp].len+1;
			node[B].par=node[x].par=nB;
			while(tmp&&node[tmp].go[w]==B){
				node[tmp].go[w]=nB;
				tmp=node[tmp].par;
			}
		}	
	}
	last=x;
}
inline void add(int from,int to){
	e[++tot].to=to;
	e[tot].next=head[from];
	head[from]=tot;
}
void dfs(int u){
	for(ri i=head[u];i;i=e[i].next){
		int v=e[i].to;
		dfs(v);
		f[u]+=f[v];
	}
	if(f[u]!=1) ans=max(ans,f[u]*node[u].len);
}
int main()
{
	scanf("%s",s);
	len=strlen(s);
	for(ri i=0;i<len;++i) Add(s[i]-'a');
	for(ri i=2;i<=ndnum;++i) add(node[i].par,i);
	dfs(1);
	printf("%lld
",ans);
    return 0;
}

后缀数组

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ri register int
#define ll long long
const int N=1000007;
int n,up=255;
int sa[N];
int len;
/*排名为 i 的后缀的位置,实质上就对应着这个后缀,
因为一个后缀对应且仅对应一个起始位置*/ 
int rk[N];
//从 i 位置开始的后缀的排名,排序的过程用不上,在求height数组中有用 
/*转化关系:sa[rk[i]]=i;rk[sa[i]]=i;
参考 log2(2^x)=x , 2^(log2(x))=x 来理解*/ 
int fir[N];
// i 位置开始的后缀用于排序的第一关键字的排名值 
int sec[N];
//第二关键字排名为 i 的后缀起始位置
int cnt[N];
// i 号元素出现了多少次,其实就是桶 
int tmp[N]; 
//用于更新fir时,保存当前的fir 
char s[1000007];
void get_sa(){
    for(ri i=0;i<len;++i) fir[i+1]=s[i];
//	for(ri i=0;i<=up;++i) cnt[i]=0;//清空桶
    for(ri i=1;i<=len;++i) ++cnt[fir[i]];
//存入到桶里 
    for(ri i=1;i<=up;++i) cnt[i]+=cnt[i-1];
//做一下前缀和,cnt 中存的就是排名了 
    for(ri i=len;i>=1;--i) sa[cnt[fir[i]]--]=i;
//得到排名,第一关键字相同时,位置靠后的排名靠后 
    int k=1;
    while(k<len){
        ri j=0;
        for(ri i=len-k+1;i<=len;++i) sec[++j]=i;
//把没有第二部分串的后缀的第二关键字按照序号排名
        for(ri i=1;i<=len;++i) 
            if(sa[i]-k>=1)
                sec[++j]=sa[i]-k;
//得到有第二部分串的后缀的第二关键字
        for(ri i=1;i<=up;++i) cnt[i]=0;
//再清空桶
        for(ri i=1;i<=len;++i) ++cnt[fir[sec[i]]];
        for(ri i=1;i<=up;++i) cnt[i]+=cnt[i-1];
        for(ri i=len;i>=1;--i) 
            sa[cnt[fir[sec[i]]]--]=sec[i];
/*依旧仿照上面,不过是以 sec[i] 为下标
用中文来说就是(高能预警):
按从大到小的顺序枚举第二关键字的排名,以'第二关键
字的排名为 i 的后缀'的第一关键字的排名,记录下这
个后缀的位置( sec[i] 就是这个后缀的位置诶)
(''是方便断句)
酱可以保证是以第一和第二关键字排的序且排名各不相
同 */
        swap(fir,tmp);
/*交换 fir 和 tmp 数组,这样在接下来的操作中,fir 被更
新为下一次排序的 fir ,而 tmp 就保存这次的 fir*/
        j=0;
        fir[sa[1]]=++j;
        for(ri i=2;i<=len;++i){
            if(sa[i]+k<=len&&sa[i-1]+k<=len&&
                tmp[sa[i]]==tmp[sa[i-1]]&&
                tmp[sa[i]+k]==tmp[sa[i-1]+k])
                fir[sa[i]]=j;
/*判断下一次第一关键字是否相同的条件,两者都必须
拥有第二部分串且它们的第一关键字和第二关键字相同*/
            else fir[sa[i]]=++j;
        }
        if(j==len) break;
        up=j;//cnt 的上界变为了 j 
        k<<=1;
    }
}
int height[N];
//排名相邻( i 和 i-1 )的两个后缀的最长公共前缀的长度,有用的一个数组 
//int h[N];虚假的数组,定义:h[i]=height[rk[i]] 
//利用性质:h[i]>=h[i-1]-1 来求 height[i] 
void get_h(){
	for(ri i=1;i<=len;++i) rk[sa[i]]=i;
	int ch=0;
	for(ri i=1;i<=len;++i){
		int t=sa[rk[i]-1];
		while(s[t+ch]==s[i+ch]) ++ch; 
		height[rk[i]]=ch;
		ch=max(0,ch-1);//性质 
	}
}
int main()
{
    scanf("%s",s);
    len=strlen(s);
    get_sa();
//    for(ri i=1;i<=len;++i) printf("%d ",sa[i]);
    get_h(); 
    return 0;
} 

哈希表

const int SZ=1991107;
struct hash_map{ 
    struct data{
        long long u;
        int v,nex;
    };
    data e[SZ<<1];
    int h[SZ],cnt;
    int hash(long long u) {return u % SZ;}
    int& operator[](long long u){
	    int hu=hash(u);
	    for(int i=h[hu];i;i=e[i].nex)
	        if(e[i].u==u)
		  	      return e[i].v;
	    return e[++cnt]=(data){u,-1,h[hu]},h[hu]=cnt,e[cnt].v;
    }
    hash_map(){
        cnt=0;
        memset(h,0,sizeof(h));
    }
    void clear(){
        cnt=0;
        memset(h,0,sizeof(h));
    }
}mp;

割点

#include<cstdio>
using namespace std;
#define ri register int
#define min(a,b) (a<b?a:b)
const int N = 100007;
int n,m,tot,head[N],dfn[N],low[N];
bool cp[N];
struct Edge{
    int to,next;
}e[N<<1];

inline void add( int from , int to );

template<class T>inline void read(T &res);

inline void tarjan( int u , int root ){
    int son = 0;
    dfn[ u ] = low[ u ] = ++tot;
    for( ri i = head[ u ] ; i ; i = e[ i ].next ){
        int v = e[ i ].to;
        if( !dfn[ v ] ){
            tarjan( v , root );
            low[ u ] = min( low[ u ] , low[ v ] );
            if( root == u ) ++son;//记录根结点的儿子 
            if( low[ v ] >= dfn[ u ] && u != root )
              cp[ u ] = true;//当v的追溯值大于u时,u就是割点 
        }
        else low[ u ] = min( low[ u ] , dfn[ v ] );
    }
    if( u == root && son >= 2 )
      cp[ u ] = true;
}

int main()
{
    read( n );read( m );
    for( ri i = 1 ; i <= m ; ++i ){
    	int u,v;
    	read( u );read( v );
    	add( u , v );add( v , u );
    }
    tot = 0;
    for( ri i = 1 ; i <= n ; ++i )
      if( !dfn[ i ] )
        tarjan( i , i );
    int cnt = 0;
    for( ri i = 1 ; i <= n ; ++i )
      if( cp[ i ] )
        ++cnt;
    printf( "%d
" , cnt );
    for( ri i = 1 ; i <= n ; ++i )
      if( cp[ i ] )
        printf( "%d " , i );
    return 0;
}

template<class T>inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' ) if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' ) res = res * 10 + ch - 48;
    res *= flag;
}

inline void add( int from , int to ){
    e[ ++tot ].to = to;
    e[ tot ].next = head[ from ];
    head[ from ] = tot;
}

负环

#include<vector>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define oo 0x3f3f3f3f 
#define RI register int 
#define N 2009 
typedef long long ll;
int T,n,m,s,dis[ N ],cnt[ N ];
//bool vis[ N ];
vector<int> e[ N ],d[ N ]; 
queue<int> q;//竞赛用了C++,能使用万能头文件和STL

template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
      res = res * 10 + ch - 48;
    res *= flag;
}

bool SPFA(){
    memset( dis , oo , sizeof( dis ) );dis[ s ] = 0;
//    memset( vis , false , sizeof( vis ) );
    memset( cnt , 0 , sizeof( cnt ) );
    q.push( s );
    while( !q.empty() ){
    	int u = q.front();q.pop();
    	cnt[ u ]++;if( cnt[ u ] > n  ) return true;//存在负环 
    	for( RI i = 0 ; i < e[ u ].size() ; i++ )
    	  if( dis[ e[ u ][ i ] ] > dis[ u ] + d[ u ][ i ] ){
    	  	  dis[ e[ u ][ i ] ] = dis[ u ] + d[ u ][ i ];
              q.push( e[ u ][ i ] );
    	  }
    }
    return false;
}

inline void clear( queue<int>& q ) {
    queue<int> empty;
    swap( empty, q );
}

int main()
{
    read( T );
    while( T-- ){
        for( RI i = 1 ; i <= n ; i++ ){e[ i ].clear();d[ i ].clear();}
        clear( q );
        read( n );read( m );
        for( RI i = 1 ; i <= m ; i++ ){
            int x,y,z;read( x );read( y );read( z );
            if( z < 0 ){
            	e[ x ].push_back( y );d[ x ].push_back( z );
            	continue;
            }
            e[ x ].push_back( y );d[ x ].push_back( z );
            e[ y ].push_back( x );d[ y ].push_back( z );
        }
        s = 1;
//	    for( register int i = 1 ; i <= n ; i++ ){
//	        e[ 0 ].push_back( i );
//	        d[ 0 ].push_back( 0 );
//	    }
        if( SPFA() ) printf( "YE5
" );
        else printf( "N0
" );
    }
    return 0;
}

二分图匹配

// luogu-judger-enable-o2
#include<cstdio>
using namespace std;
#define ri register int 
#define iv inline void
const int N = 1000010,XN = 2009;
int n,m,E,tot = 0,ans = 0,vis[ XN ],head[ XN ],match[ XN ];
struct Edge{int to,next;}e[ N ];
iv add( int from , int to ){
    e[ ++tot ].next = head[ from ];
    e[ tot ].to = to;head[ from ] = tot;
}
bool dfs( int x , int timer ){
    if( vis[ x ] == timer ) return false;//有环 
    vis[ x ] = timer;
    for( ri j = head[ x ] ; j ; j = e[ j ].next )
      if( !match[ e[ j ].to ] || dfs( match[ e[ j ].to ] , timer ) ){
      	  match[ e[ j ].to ] = x;
      	  return true;
      }
    return false;
}
template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
      res = res * 10 + ch - 48;
    res *= flag;
}
int main(){
    read( n );read( m );read( E );
    for( ri i = 1 ; i <= E ; i++ ){
        int a,b;read( a );read( b );
        if( a > n || b > m ) continue;
        add( a , b + n );
    }
    for( ri i = 1 ; i <= n ; i++ ) if( dfs( i , i ) ) ans++;
    printf( "%d
" , ans );
    return 0;
}

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 1000005

template<class T>
inline void read(T &res)
{
    static char ch;
        T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
          if( ch == '-' )
            flag = -1;
        res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
          res = res * 10 + ch - 48;
        res *= flag;
}

struct dui{//小根堆 
    int n[ N << 2 ];
    int cnt;
    inline int size(){                                           
        return cnt;                                          
    }
    inline int top(){
        return n[ 1 ];
    }
    inline void push( int x ){
        n[ ++cnt ] = x;
        int ord = cnt;
        while( n[ ord ] < n[ ord >> 1] ){
            swap( n[ ord ] , n[ ord >> 1] );
            ord = ord >> 1;
        }
    }
    inline void pop(){
        swap( n[ cnt ] , n[ 1 ] );
        cnt--;
        int ord = 1;
        while( ( ord << 1 ) <= cnt ){//保证有儿子 
            int next = ( ord << 1 );
            if( next < cnt && n[ next + 1 ] < n[next] )
              next++;
            if( n[ ord ] <= n[ next ] ) 
              break;
            swap( n[ ord ] , n[ next ] );
            ord = next;                      
        } 
    }
    inline bool empty(){
        if( !cnt )
          return true;
        return false;
    }
    dui(){
        cnt = 0;
    }
}q;

int main()
{
    int n;
    cin>>n;
    for( register int i = 1 ; i <= n ; i ++ ){
        int x;
        read( x );
        switch( x ){
            case 1:{
                int y;
                read( y );
                q.push( y );
                break;
            }
            case 2:{
                printf( "%d
" , q.top() );
                break;
            }
            case 3:{
                q.pop();
                break;
            }
        }
    }
    return 0;
}

堆优化dij

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define oo 0x3f3f3f3f
#define N 200010
int n,m,start,eeee,tot = 0,dis[ N / 2 ],head[ N / 2 ];
bool vis[ N / 2 ];

struct Node{
    int to,dis;
};

struct node{
    int to,next,dis;
}e[ N ];

struct dui{
    Node n[ N * 4 ];
    int cnt;
    inline int size(){                                           
        return cnt;                                       
    }
    inline Node top(){
        return n[ 1 ];
    }
    inline void push( Node x ){
        n[ ++cnt ] = x;
        int ord = cnt;
        while( n[ ord ].dis < n[ ord >> 1].dis ){
            swap( n[ ord ] , n[ ord >> 1] );
            ord = ord >> 1;
        }
    }
    inline void pop(){
        swap( n[ cnt ] , n[ 1 ] );
        cnt--;
        int ord = 1;
        while( ord * 2 <= cnt ){
            int next = ord * 2 ;
            if( next < cnt && n[ next + 1 ].dis < n[ next ].dis )
              next++;
            if( n[ ord ].dis <= n[ next ].dis ) 
              break;
            swap( n[ ord ] , n[ next ] );
            ord = next;                      
        } 
    }
    inline bool empty(){
        if( !cnt ) return true;
        return false;
    }
    dui(){cnt=0;}
}q;//小根堆 

template<class T>
inline void read(T &res){
    static char ch;T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' ) flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
      res = res * 10 + ch - 48;
    res *= flag;
}

inline void add( int from , int to , int Distance ){
    e[ ++tot ].to = to;
    e[ tot ].next = head[ from ];
    e[ tot ].dis = Distance;
    head[ from ] = tot;
}

int main()
{
    read( n );read( m );read( start );read(eeee);
    for( register int i = 1 ; i <= m ; i++ ){
    	int x,y,d;
    	read( x );read( y );read( d );
    	add( x , y , d );
    }
    memset( vis , false , sizeof( vis ) );
    memset( dis , oo , sizeof( dis ) );
    dis[ start ] = 0;
    Node s = { start , 0 };q.push( s );
    while( !q.empty() ){
    	int u = q.top().to,d = q.top().dis;q.pop();
    	if( vis[ u ] ) continue;
    	vis[ u ] = true;
    	for( register int i = head[ u ] ; i ; i = e[ i ].next )
    	  if( !vis[ e[ i ].to ] && dis[ e[ i ].to ] > dis[ u ] + e[ i ].dis ){
    	  	  dis[ e[ i ].to ] = dis[ u ] + e[ i ].dis;
    	  	  Node p = { e[ i ].to , dis[ e[ i ].to ] };
    	  	  q.push( p );
    	  }
    }
//    for( register int i = 1 ; i <= n ; i++ )
//      printf( "%d " , dis[ i ] );
	printf("%d
",dis[eeee]);
    return 0;
}

并查集

#include<bits/stdc++.h>
using namespace std;
int father[100005];
void unionn(int x,int y)//集合合并
{
    father[y]=x;
}

int find(int x)//寻找根结点编号并压缩路径
{
    if(father[x]!=x) 
      father[x]=find(father[x]);//将x的最近父结点更新为根结点 
    return father[x];
} 

bool judge(int x,int y)//判断两个元素是否属于一个集合 
{
    x=find(x);
    y=find(y);
    if(x==y)
      return true;
    else
      return false;
}

void mergee(int x,int y)
{
    int r1=find(x);
    int r2=find(y);//找到元素的祖先 
    if(r1!=r2)
      unionn(r1,r2);//集合合并 
    //直接将  x的根结点r1  更新为  y的根结点r2  的根结点
    //,相当于将以r2为代表的集合
    //放到以r1为代表的集合内,并删除集合r2 
}

void search(int x1,int y1)
{
    if(judge(x1,y1))//判断元素是否在同一个集合 
      printf("Y
");
    else
      printf("N
");
} 
 
int main()
{ 
    //freopen("relation.in","r",stdin);
    //freopen("relation.out","w",stdout);
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    father[i]=i;//初始化,分离集合,每个结点的父结点是他自己
    for(int i=1;i<=m;i++)
    {
        int z,x,y;
        scanf("%d%d%d",&z,&x,&y);
        if(z==1)//合并 
          mergee(x,y);
        else if(z==2)
          search(x,y);
    }  
    return 0;
}

Treap

#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
const int N=200000;
int n,ndnum,T,root=0;
struct Treap{
    int size,cnt,ls,rs,dat,val;
    #define size(x) a[x].size
    #define cnt(x) a[x].cnt
    #define ls(x) a[x].ls
    #define rs(x) a[x].rs
    #define val(x) a[x].val
    #define dat(x) a[x].dat
}a[N];
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
inline int New(int x){
    a[++ndnum].val=x;
    a[ndnum].dat=rand();
    a[ndnum].cnt=a[ndnum].size=1;
    return ndnum;
}
inline void update(int p){
    a[p].size=a[ls(p)].size+a[rs(p)].size+a[p].cnt;
}
inline void Zig(int &p){
    int q=ls(p);
    ls(p)=rs(q);
    rs(q)=p;
    p=q;
    update(p);
    update(rs(p));
}
inline void Zag(int &p){
    int q=rs(p);
    rs(p)=ls(q);
    ls(q)=p;
    p=q;
    update(p);
    update(ls(p));
}
void Insert(int &p,int x){
    if(p==0) p=New(x);
    else if(x==val(p)) ++cnt(p);
    else if(x<a[p].val){
        Insert(ls(p),x);
        if(dat(p)<dat(ls(p))) Zig(p);
    }
    else if(x>a[p].val){
        Insert(rs(p),x);
        if(dat(p)<dat(rs(p))) Zag(p);
    }
    update(p);
}
void Del(int &p,int x){
    if(p==0) return;
    if(x==val(p)){
        if(cnt(p)>1) --cnt(p);
        else if(ls(p)||rs(p)){
            if(rs(p)==0||dat(ls(p))>dat(rs(p))){
                Zig(p);
                Del(rs(p),x);
            }
            else{
                Zag(p);
                Del(ls(p),x);
            }
        }
        else p=0;
    }
    else x<val(p)?Del(ls(p),x):Del(rs(p),x);
    update(p);
}
int Rank(int p,int x){
    if(x==val(p)) return size(ls(p))+1;
    if(x<val(p)) return Rank(ls(p),x);
    else return size(ls(p))+cnt(p)+Rank(rs(p),x);
}
int Search(int p,int rk){
    if(rk<=size(ls(p))) return Search(ls(p),rk);
    if(rk<=size(ls(p))+cnt(p)) return val(p);
    else return Search(rs(p),rk-size(ls(p))-cnt(p));
}
inline int Pre(int x){
    int p=root,ans=-0x7fffffff;
    while(p){
        if(val(p)<x&&val(p)>ans)
          ans=val(p);
        if(x==val(p)){
            p=ls(p);
            while(p){
                ans=val(p);
                p=rs(p);
            }
            break;
        }
        else if(x<val(p)) p=ls(p);
        else if(x>val(p)) p=rs(p);
    }
    return ans;
}
inline int Next(int x){
    int p=root,ans=0x7fffffff;
    while(p){
        if(val(p)>x&&val(p)<ans)
          ans=val(p);
        if(x==val(p)){
            p=rs(p);
            while(p){
                ans=val(p);
                p=ls(p);
            }
            break;
        }
        else if(x<val(p)) p=ls(p);
        else if(x>val(p)) p=rs(p);
    }
    return ans;
}
int main()
{
    srand(time(0)); 
    read(T);
    while(T--){
        int opt,x;
        read(opt);read(x);
        if(opt==1) Insert(root,x);
        else if(opt==2) Del(root,x);
        else if(opt==3) printf("%d
",Rank(root,x));
        else if(opt==4) printf("%d
",Search(root,x));
        else if(opt==5) printf("%d
",Pre(x));
        else if(opt==6) printf("%d
",Next(x));
    } 
    return 0;
}

st表

#include<bits/stdc++.h>
using namespace std;
#define N 100050
int n,m,l;
int a[ N ][ 25 ],lg2[ N + 50 ];

inline int max( int x , int y ){
    return x > y ? x : y;
}

inline int min( int x , int y ){
    return x < y ? x : y;
}

template<class T>
inline void read(T &res){
    static char ch;
    T flag = 1;
    while( ( ch = getchar() ) < '0' || ch > '9' )
      if( ch == '-' )
    flag = -1;
    res = ch - 48;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
    res = res * 10 + ch - 48;
    res *= flag;
}

inline int maxn( int l , int r ){
    int k = lg2[ r - l + 1 ];
    return max( a[ l ][ k ] , a[ r - ( 1 << k ) + 1 ][ k ] );
}

int main()
{
    read( n ),read( m );
    for( register int i = 1 ; i <= n ; i++ )
      read( a[ i ][ 0 ] );
    for( register int i = 2 ; i <= 100000 ; i++ )
      lg2[ i ] = lg2[ i / 2 ] + 1;
    int l = lg2[ n ] + 1;
    for( register int j = 1 ; j <= l ; j++ )
      for( register int i = 1 ; i + ( 1 << j ) - 1 <= n ; i++ ) 
        a[ i ][ j ] = max( a[ i ][ j - 1 ] , a[ i + ( 1 << ( j - 1 ) ) ][ j - 1 ] );
    for( register int i = 1 ; i <= m ; i++ ){
        int x,y;
        read( x ),read( y );
        printf( "%d
" , maxn( x , y ) );
    }
    return 0;
}

Splay

#include<cstdio>
using namespace std;
#define ri register int
#define ll long long
const int N=200007;
int n;
template<class T>inline void read(T &res){
    static char son;T flag=1;
    while((son=getchar())<'0'||son>'9') if(son=='-') flag=-1;
    res=son-48;
    while((son=getchar())>='0'&&son<='9') res=(res<<1)+(res<<3)+son-48;
    res*=flag;
}
class Splay{
    public:
        int root,tot=0,fa[N],size[N],cnt[N],val[N],son[N][2];
    private:
        void update(int p){
            size[p]=size[son[p][0]]+size[son[p][1]]+cnt[p];
        }
        int check(int p){
            return p==son[fa[p]][1];
        }
        void rotate(int p){
            int f=fa[p],ff=fa[f],k=check(p),kk=check(f),sp=son[p][k^1];
            son[p][k^1]=f;fa[f]=p;
            son[f][k]=sp;fa[sp]=f;
            son[ff][kk]=p;fa[p]=ff;
            update(f);update(p);
        }
        void splay(int p,int goal){
            if(p==goal) return;//易忘
            while(fa[p]!=goal){
                int f=fa[p],ff=fa[f];
                if(ff!=goal){
                    if(check(p)==check(f)) rotate(f);
                    else rotate(p);
                }
                rotate(p);
            }
            if(goal==0)	root=p;//易忘 
        }//把p   Splay到goal的儿子
        void find(int x){
            int cur=root;
            while(son[cur][x>val[cur]]&&x!=val[cur])
                cur=son[cur][x>val[cur]];
            splay(cur,0);
        }
    public:
        int rank(int x){
            find(x);
            return size[son[root][0]]+1;
        }
        void insert(int x){
            int cur=root,p=0;//p是cur的父亲
            while(cur&&x!=val[cur]){
                p=cur;
                cur=son[cur][x>val[cur]];
            }
            if(cur) ++cnt[cur];//找到了x 
            else{
                cur=++tot;
//                son[cur][0]=son[cur][1]=0;
                fa[cur]=p;
                val[cur]=x;
                cnt[cur]=size[cur]=1;//要赋全 
                if(p) son[p][x>val[p]]=cur;//一定要判断
            }
            splay(cur,0);
        }
        int pre(int x){
            find(x);
            if(val[root]<x) return root;
            int p=son[root][0];
            while(son[p][1]) p=son[p][1];
            return p;
        }//记得返回的是位置而不是实际的值 
        int nxt(int x){
            find(x);
            if(val[root]>x) return root;
            int p=son[root][1];
            while(son[p][0]) p=son[p][0];
            return p;
        }
        void del(int x){
            int pr=pre(x),nt=nxt(x);
            splay(pr,0);splay(nt,pr);
            int p=son[nt][0];
            if(cnt[p]>1){
                --cnt[p];
                splay(p,0);
            }
            else son[nt][0]=0;
            update(nt);update(root);
        }
        int search(int rk){
            int p=root;
            while(1){
                if(son[p][0]&&rk<=size[son[p][0]]) p=son[p][0];//一定要判断是否有儿子 
                else if(rk>size[son[p][0]]+cnt[p]){
                    rk-=size[son[p][0]]+cnt[p];
                    p=son[p][1];//注意顺序
                }
                else{
                	splay(p,0);
                	return p;
				}
            }
        }
}Tree;
int main()
{
    Tree.insert(2147483647);
    Tree.insert(-2147483647);
    read(n);
    while(n--){
        int opt,x;
        read(opt);
        read(x);
        switch(opt){
            case 1:{
                Tree.insert(x);
                break;
            }
            case 2:{
                Tree.del(x);
                break;
            }
            case 3:{
                printf("%d
",Tree.rank(x)-1);
                break;
            }
            case 4:{
                printf("%d
",Tree.val[Tree.search(x+1)]);
                break;
            }
            case 5:{
                printf("%d
",Tree.val[Tree.pre(x)]);
                break;
            }
            case 6:{
                printf("%d
",Tree.val[Tree.nxt(x)]);
                break;
            }
        }
    }
    return 0;
}

nim博弈

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int T,n,x,y;
template<class T>inline void read(T &res){
	static char ch;T flag=1;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') flag=-1; res=ch-48;
	while((ch=getchar())>='0'&&ch<='9') res=(res<<1)+(res<<3)+ch-48; res*=flag;
}
int main()
{
	read(T);
	while(T--){
		read(n);
		x=0;
		while(n--){
			read(y);
			x^=y;
		}
		printf(x?"Yes
":"No
");
	}
    return 0;
}
原文地址:https://www.cnblogs.com/hzyhome/p/11867194.html