• 最后的财产——模板大全


    @

    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;
    }
    
  • 相关阅读:
    Eclipse报错:An internal error has occurred. Widget is disposed
    服务器端解决跨域问题的三种方法
    为什么要使用NoSQL
    Mybatis 中$与#的区别
    maven 打包命令,跳过测试
    maven打包跳过测试命令
    Vue 扩展插件
    node 文件打开状态
    node buffer缓冲区
    npm 命令
  • 原文地址:https://www.cnblogs.com/hzyhome/p/11867194.html
Copyright © 2020-2023  润新知