• Templates


    Game theory

    Nim

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		int n,x,res=0;
    		scanf("%d",&n);
    		while(n--){
    			scanf("%d",&x);
    			res^=x;
    		}
    		puts(res==0?"No":"Yes");
    	}
    	return 0;
    }
    

    SG function

    
    

    Graph theory

    SPFA

    void spfa(int start){
    	for(int i=1;i<=n;i++)dis[i]=INF,vis[i]=0;
    	dis[start]=0;
    	q[qhead=qtail=1]=start;
    	while(qhead<=qtail){
    		int u=q[qhead++];
    		vis[u]=0;
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].to;
    			if(dis[u]+e[i].w<dis[v]){
    				dis[v]=dis[u]+e[i].w;
    				if(!vis[v]){
    					vis[v]=1;
    					q[++qtail]=v;
    				}
    			}
    		}
    	}
    }
    

    SPFA check negative cycles

    void spfa(){
        for(int i=1;i<=n;i++)cnt[i]=vis[i]=0,dis[i]=INF;
        dis[1]=0;
        queue<int> q;
        q.push(1);
        while(!q.empty()){
            int u=q.top();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to,w=e[i].w;
                D w=e[i].a*dis[u]+e[i].b;
                if(dis[u]+w<dis[v]&&cnt[v]<=n){
                    dis[v]=w;
                    if(++cnt[v]>n)dis[v]=-INF;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    

    Dijkstra

    void dijkstra(int st){
    	for(int i=1;i<=n;i++){
    		dis[i]=INF;
    		vis[i]=0;
    	}
    	dis[st]=0;
    	priority_queue<P,vector<P>,greater<P> > q;
    	q.push(P(0,st));
    	while(!q.empty()){
    		int u=q.top().second,v;
    		q.pop();
    		if(vis[u])continue;
    		vis[u]=1;
    		for(int i=head[u];i;i=e[i].next){
    			v=e[i].to;
    			if(dis[u]+e[i].w<dis[v]&&!vis[v]){
    				dis[v]=dis[u]+e[i].w;
    				q.push(P(dis[v],v));
    			}
    		}
    	}
    }
    

    Floyd

    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    

    Floyd求路径最值限制问题

    例:过路费

    有一天你来到了一个奇怪的国家,它有 (N) 个城市,城市之间有若干条双向道路连接,每条道路都有一定的费用,经过城市也要一定的费用。从一个城市到达另一个城市的总花费为路径上费用最大的城市费用(包括起点和终点)加上路径上所有的道路的费用。给出 (Q) 次询问,分别回答每次询问中两城市间的最少花费。保证城市之间可以互达。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=303,INF=0x3f3f3f3f;
    int n,m,Q,p[maxn],a[maxn],g[maxn][maxn],dp[maxn][maxn];
    bool cmp(int x,int y){return a[x]<a[y];}
    void floyd(int k){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",a+i);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)dp[i][j]=g[i][j]=INF;
            g[i][i]=0;
            p[i]=i;
        }
        sort(p+1,p+n+1,cmp);
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            g[u][v]=g[v][u]=min(g[u][v],w);
        }
        for(int l=1,r=1;l<=n;l=r){
            for(;r<=n&&a[p[l]]==a[p[r]];r++){
                floyd(p[r]);
            }
            for(int _i=1;_i<r;_i++){
                int i=p[_i];
                for(int _j=1;_j<r;_j++){
                    int j=p[_j];
                    dp[i][j]=min(dp[i][j],g[i][j]+a[p[l]]);
                }
            }
        }
        scanf("%d",&Q);
        while(Q--){
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",dp[x][y]);
        }
        return 0;
    }
    

    SCC

    void tarjan(int u){
        dfn[u]=low[u]=++cntdfn;
        stk[++top]=u;
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!incyc[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u]){
            numcyc[++cntcyc]=0;
            int x;
            do{
                x=stk[top];
                top--;
                numcyc[cntcyc]++;
                incyc[x]=cntcyc;
            }while(x!=u);
        }
    }
    void getcyc(){
        for(int i=1;i<=n;i++){
            if(!dfn[i])tarjan(i);
        }
    }
    

    topological-sort

    void topsort(){
    	queue<int> q;
    	for(int i=1;i<=n;i++){
    		if(indeg[i]==0){
    			q.push(i);
    		}
    	}
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].to;
    			if(--indeg[v]==0){
    				q.push(v);
    			}
    		}
    	}
    }
    

    bipartite-graph max-match (Hungary algorithm)

    bool dfs(int u){
        for(int i=0;i<int(g[u].size());i++){
            int v=g[u][i];
            if(vis[v])continue;
            vis[v]=1;
            if(!c[v]||dfs(c[v])){
            	d[u]=v;
                c[v]=u;
                return 1;
            }
        }
        return 0;
    }
    int match(){
        int ret=0;
        for(int i=1;i<=n1;i++){
            for(int j=1;j<=n2;j++)vis[j]=0;
            if(dfs(i))ret++;
        }
        return ret;
    }
    int main(){
        scanf("%d%d%d",&n1,&n2,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
        }
        printf("%d
    ",match());
        return 0;
    }
    

    bipartite-graph max-match in minimum lexicographic order (Hungary algorithm)

    bool dfs(int u){
        for(int i=0;i<int(g[u].size());i++){
            int v=g[u][i];
            if(vis[v])continue;
            vis[v]=1;
            if(!c[v]||dfs(c[v])){
            	d[u]=v;
                c[v]=u;
                return 1;
            }
        }
        return 0;
    }
    int match(){
        int ret=0;
        for(int i=n1;i>=1;i--){
            for(int j=1;j<=n2;j++)vis[j]=0;
            if(dfs(i))ret++;
        }
        return ret;
    }
    int main(){
        scanf("%d%d%d",&n1,&n2,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
        }
        for(int i=1;i<=n1;i++)sort(g[i].begin(),g[i].end());
        printf("%d
    ",match());
        return 0;
    }
    

    bipartite-graph perfect-match in maximum weight (KM-algorithm)

    bool dfs(int u){
        visd[u]=1;
        for(int v=1;v<=n;v++){
            int tmp=ld[u]+lc[v]-g[u][v];
            if(!visc[v]&&!tmp){
                visc[v]=1;
                if(!c[v]||dfs(c[v])){
                    c[v]=u;
                    return 1;
                }
            }
            else if(tmp<slack[v]){
                slack[v]=tmp;
            }
        }
        return 0;
    }
    int km(){
        for(int i=1;i<=n;i++){
            c[i]=lc[i]=ld[i]=0;
            for(int j=1;j<=n;j++){
                ld[i]=max(ld[i],g[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)slack[j]=INF;
            while(1){
                for(int j=1;j<=n;j++)visc[j]=visd[j]=0;
                if(dfs(i))break;
                int res=INF;
                for(int v=1;v<=n;v++){
                    if(!visc[v]){
                        res=min(res,slack[v]);
                    }
                }
                for(int u=1;u<=n;u++){
                    if(visd[u]){
                        ld[u]-=res;
                    }
                }
                for(int v=1;v<=n;v++){
                    if(visc[v]){
                        lc[v]+=res;
                    }
                    else{
                        slack[v]-=res;
                    }
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)ans+=ld[i]+lc[i];
        return ans;
    }
    

    network-flow (Dinic)

    bool bfs(){
    	for(int i=1;i<=n;i++)dep[i]=0,head1[i]=head[i];
    	dep[s]=1;
    	int *qhead=q,*qtail=q;
    	*qtail++=s;
    	while(qhead!=qtail){
    		int u=*qhead++;
    		for(int i=head[u];~i;i=e[i].next){
    			int v=e[i].to;
    			if(e[i].w&&dep[v]==0){
    				dep[v]=dep[u]+1;
    				*qtail++=v;
    			}
    		}
    	}
    	return dep[t]!=0;
    }
    int dfs(int u,int low){
    	if(low==0||u==t)return low;
    	int flow=0;
    	for(int &i=head1[u];~i;i=e[i].next){
    		int v=e[i].to;
    		if(e[i].w&&dep[v]==dep[u]+1){
    			int tmp=dfs(v,min(low,e[i].w));
    			if(tmp==0)dep[v]=0;
    			else{
    				flow+=tmp;
    				low-=tmp;
    				e[i].w-=tmp;
    				e[i^1].w+=tmp;
    				if(low==0)break;
    			}
    		}
    	}
    	return flow;
    }
    int dinic(){
    	int ans=0;
    	while(bfs())ans+=dfs(s,INF);
    	return ans;
    }
    int main(){
    	int m;
    	scanf("%d%d%d%d",&n,&m,&s,&t);
    	for(int i=1;i<=n;i++)head[i]=-1;
    	cnte=-1;
    	while(m--){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		addedge(u,v,w);
    	}
    	printf("%d",dinic());
    	return 0;
    }
    

    network-flow (SPFA+EK)

    bool spfa(){
    	for(int i=1;i<=n;i++)flow[i]=dis[i]=INF,vis[i]=0;
    	pre[t]=-1;
    	dis[s]=0;
    	queue<int> q;
    	q.push(s);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=head[u];~i;i=e[i].next){
    			int v=e[i].to;
    			if(e[i].w>0&&dis[u]+e[i].cost<dis[v]){
    				dis[v]=dis[u]+e[i].cost;
    				pre[v]=u;
    				edg[v]=i;
    				flow[v]=min(flow[u],e[i].w);
    				if(!vis[v]){
    					vis[v]=1;
    					q.push(v);
    				}
    			}
    		}
    	}
    	return pre[t]!=-1;
    }
    void micmxf(){
    	while(spfa()){
    		int x=t;
    		while(x!=s){
    			e[edg[x]].w-=flow[t];
    			e[edg[x]^1].w+=flow[t];
    			x=pre[x];
    		}
    		maxflow+=flow[t];
    		mincost+=flow[t]*dis[t];
    	}
    }
    int main(){
    	int m;
    	scanf("%d%d%d%d",&n,&m,&s,&t);
    	for(int i=0;i<=n;i++)head[i]=-1;
    	cnte=-1;
    	for(int i=1;i<=m;i++){
    		int u,v,w,cost;
    		scanf("%d%d%d%d",&u,&v,&w,&cost);
    		add(u,v,w,cost);
    		add(v,u,0,-cost);
    	}
    	micmxf();
    	printf("%d %d
    ",maxflow,mincost);
    	return 0;
    }
    

    MST (Prim)

    void prim(){
        for(int i=1;i<=n;i++)dis[i]=INT_MAX;
        priority_queue<pii,vector<pii>,greater<pii> > q;
        q.push(make_pair(0,1));
        while(!q.empty()){
            int d=q.top().first,u=q.top().second;
            q.pop();
            if(vis[u])continue;
            ans+=d;
            vis[u]=1;
            cnt++;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]>e[i].w&&!vis[v]){
                    dis[v]=e[i].w;
                    q.push(make_pair(dis[v],v));
                }
            }
        }
    }
    

    MST (Kruskal)

    void kruskal(){
        sort(e+1,e+m+1);
        ufset s(n);
        for(int i=1;i<=m;i++){
            int u=e[i].from,v=e[i].to;
            if(s.same(u,v))continue;
            ans+=e[i].w;
            s.Union(u,v);
            if(++tot==n-1)break;
        }
    }
    

    Strictly second-best MST

    #include<bits/stdc++.h>
    #define maxn 100003
    #define maxm 300003
    #define INF 100000000000000000ll
    using namespace std;
    typedef long long D;
    D n,m,lg[maxn];
    namespace G{
        struct edge{
            D from,to,w;
            bool vis;
            bool operator <(const edge& x)const{return w<x.w;}
        }e[maxm];
        D cnte;
        void add(D u,D v,D w){e[++cnte]=(edge){u,v,w,0};}
    }
    namespace MST{
        struct edge{
            D to,next,w;
        }e[maxn<<1];
        D head[maxn],cnte,dep[maxn],fa[maxn][23],mx[maxn][23][2];
        void add(D u,D v,D w){e[++cnte]=(edge){v,head[u],w},head[u]=cnte;}
        void calc(D &X0,D &X1,D Y0,D Y1,D Z0,D Z1){
            X0=max(Y0,Z0);
            if(Y0!=Z0)X1=max(min(Y0,Z0),max(Y1,Z1));
            else X1=max(Y1,Z1);
        }
        void init(D u,D last){
            fa[u][0]=last;
            dep[u]=dep[last]+1;
            for(D i=1;(1<<i)<=dep[u];i++){
                D up=fa[u][i-1];
                fa[u][i]=fa[up][i-1];
                calc(mx[u][i][0],mx[u][i][1],mx[u][i-1][0],mx[u][i-1][1],mx[up][i-1][0],mx[up][i-1][1]);
            }
            for(D i=head[u];i;i=e[i].next){
                D v=e[i].to;
                if(v==last)continue;
                mx[v][0][0]=e[i].w;
                init(v,u);
            }
        }
        D lca(D x,D y){
            if(dep[x]<dep[y])swap(x,y);
            while(dep[x]>dep[y]){
                x=fa[x][lg[dep[x]-dep[y]]];
            }
            if(x==y)return x;
            for(D i=lg[dep[x]];i>=0;i--){
                if(fa[x][i]!=fa[y][i]){
                    x=fa[x][i];
                    y=fa[y][i];
                }
            }
            return fa[x][0];
        }
        D query(D x,D y,D w){
            D l=lca(x,y);
            D ans0=0,ans1=0;
            while(x!=l){
                calc(ans0,ans1,ans0,ans1,mx[x][lg[dep[x]-dep[l]]][0],mx[x][lg[dep[x]-dep[l]]][1]);
                x=fa[x][lg[dep[x]-dep[l]]];
            }
            while(y!=l){
                calc(ans0,ans1,ans0,ans1,mx[y][lg[dep[y]-dep[l]]][0],mx[y][lg[dep[y]-dep[l]]][1]);
                y=fa[y][lg[dep[y]-dep[l]]];
            }
            if(w!=ans0)return w-ans0;
            if(ans1)return w-ans1;
            return INF;
        }
    }
    D f[maxn];
    D find(D x){
        if(x!=f[x])f[x]=find(f[x]);
        return f[x];
    }
    D kruskal(){
        D cnt=0,ret=0;
        sort(G::e+1,G::e+m+1);
        for(D i=1;i<=n;i++)f[i]=i;
        for(D i=1;i<=m;i++){
            D u=G::e[i].from,v=G::e[i].to,fu=find(u),fv=find(v);
            if(fu!=fv){
                f[fu]=fv;
                ret+=G::e[i].w;
                G::e[i].vis=1;
                MST::add(u,v,G::e[i].w);
                MST::add(v,u,G::e[i].w);
                cnt++;
                if(cnt>=n)break;
            }
        }
        return ret;
    }
    signed main(){
        scanf("%lld%lld",&n,&m);
        for(D i=1;i<=m;i++){
            D u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            G::add(u,v,w);
        }
        D ans1=kruskal(),ans2=INF;
        for(D i=2;i<maxn;i++)lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i);
        MST::init(1,0);
        for(D i=1;i<=m;i++){
            if(!G::e[i].vis){
                D u=G::e[i].from,v=G::e[i].to;
                ans2=min(ans2,MST::query(u,v,G::e[i].w));
            }
        }
        printf("%lld
    ",ans1+ans2);
        return 0;
    }
    

    LCA (Heavy-light decomposition)

    void initdep(int u,int last){
    	sz[u]=1;
    	fa[u]=last;
    	int mx=0;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa[u])continue;
    		dep[v]=dep[u]+1;
    		initdep(v,u);
    		sz[u]+=sz[v];
    		if(sz[v]>mx)mx=sz[v],son[u]=v;
    	}
    }
    void initdfn(int u,int tp){
    	dfn[u]=++cntdfn;
    	num[cntdfn]=u;
    	top[u]=tp;
    	if(son[u]){
    		initdfn(son[u],tp);
    	}
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa[u]||v==son[u])continue;
    		initdfn(v,v);
    	}
    	rig[u]=cntdfn;
    }
    int lca(int x,int y){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		x=fa[top[x]];
    	}
    	if(dep[x]<dep[y])swap(x,y);
    	return y;
    }
    

    LCA (ST RMQ)

    void init(int u,int last){
        st[++cntdfn][0]=u;
        dfn[u]=cntdfn;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==last)continue;
            dep[v]=dep[u]+1;
            init(v,u);
            st[++cntdfn][0]=u;
        }
    }
    int MIN(int x,int y){return dep[x]<dep[y]?x:y;}
    void initst(){
        for(int len=1;(1<<len)<=cntdfn;len++){
            for(int i=1;i+(1<<len)-1<=cntdfn;i++){
                st[i][len]=MIN(st[i][len-1],st[i+(1<<(len-1))][len-1]);
            }
        }
    }
    int lca(int x,int y){
        if(dfn[x]>dfn[y])swap(x,y);
        int tmp=lg[dfn[y]-dfn[x]+1];
        return MIN(st[dfn[x]][tmp],st[dfn[y]-(1<<tmp)+1][tmp]);
    }
    

    LCA (doubling)

    void init(int u){
        for(int i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u][0])continue;
            fa[v][0]=u;
            dep[v]=dep[u]+1;
            init(v);
        }
    }
    int lca(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]];
        if(x==y)return x;
        for(int i=lg[dep[x]];i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    

    Virtual tree

    例:[SDOI2011]消耗战

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=250003,maxm=500003,INF=0x3f3f3f3f;
    struct edge{int to,next,w;}e[maxn<<1];
    int head[maxn],cnte;
    void add(int u,int v,int w){e[++cnte].to=v,e[cnte].w=w,e[cnte].next=head[u],head[u]=cnte;}
    int n,lg[maxn],fa[maxn][23],cntdfn,dfn[maxn],rig[maxn],dep[maxn],p[maxn<<2],
    mi[maxn],stk[maxn],top;
    long long dp[maxn];
    bool vis[maxn];
    void init(int u,int last){
    	dfn[u]=++cntdfn;
    	fa[u][0]=last;
    	for(int i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last)continue;
    		dep[v]=dep[u]+1;
    		mi[v]=min(mi[u],e[i].w);
    		init(v,u);
    	}
    	rig[u]=++cntdfn;
    }
    int lca(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]];
    	if(x==y)return x;
    	for(int i=lg[dep[x]];i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    bool cmp(int x,int y){return (x>0?dfn[x]:rig[-x])<(y>0?dfn[y]:rig[-y]);}
    int main(){
    	for(int i=2;i<maxn;i++)lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i);
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w),add(v,u,w);
    	}
    	mi[1]=INF;
    	init(1,0);
    	int Q;
    	scanf("%d",&Q);
    	while(Q--){
    		int m;
    		scanf("%d",&m);
    		for(int i=1;i<=m;i++)scanf("%d",p+i),vis[p[i]]=1,dp[p[i]]=mi[p[i]];
    		sort(p+1,p+m+1,cmp);
    		for(int i=2;i<=m;i++){
    			int l=lca(p[i-1],p[i]);
    			if(vis[l])continue;
    			vis[l]=1;
    			p[++m]=l;
    		}
    		for(int i=m;i>=1;i--)p[++m]=-p[i];
    		if(!vis[1]){
    			p[++m]=1,p[++m]=-1;
    			vis[1]=1;
    		}
    		sort(p+1,p+m+1,cmp);
    		top=0;
    		for(int i=1;i<m;i++){
    			if(p[i]>0){
    				stk[++top]=p[i];
    			}
    			else{
    				int u=stk[top--],last=stk[top];
    				dp[last]+=min(dp[u],(long long)mi[u]);
    				vis[u]=0,dp[u]=0;
    			}
    		}
    		printf("%lld
    ",dp[1]);
    		vis[1]=0,dp[1]=0;
    	}
    	return 0;
    }
    

    Tree-plus-cycle (containing multiple edges)

    bool init(int u){
    	stk[++top]=u;
    	instk[u]=1;
    	for(int i=head[u];i;i=e[i].next){
    		int id=(i+1)>>1;
    		if(vis[id])continue;
    		vis[id]=1;
    		int v=e[i].to;
    		if(instk[v]){
    			int x;
    			do{
    				x=stk[top--];
    				p[++tot]=x;
    			}while(x!=v);
    			return 1;
    		}
    		if(init(v))return 1;
    	}
    	top--;
    	return 0;
    }
    

    Divide-and-conquer on tree

    例:【模板】点分治

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=10003,INF=0x3f3f3f3f;
    struct edge{int to,next,w;}e[maxn<<1];
    int head[maxn],cnte;
    void add(int u,int v,int w){e[++cnte].to=v,e[cnte].w=w,e[cnte].next=head[u],head[u]=cnte;}
    int n,m,k,dis[maxn],cntdis;
    bool vis[maxn];
    namespace GG{
    	int sz[maxn],G,szG;
    	int inittrsz(int u,int last){
    		int trsz=1;
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].to;
    			if(v==last||vis[v])continue;
    			trsz+=inittrsz(v,u);
    		}
    		return trsz;
    	}
    	void getG1(int u,int last,int trsz){
    		int ret=0;
    		sz[u]=1;
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].to;
    			if(v==last||vis[v])continue;
    			getG1(v,u,trsz);
    			ret=max(ret,sz[v]);
    			sz[u]+=sz[v];
    		}
    		ret=max(ret,trsz-sz[u]);
    		if(ret<szG){
    			szG=ret;
    			G=u;
    		}
    	}
    	int getG(int u){
    		int trsz=inittrsz(u,0);
    		szG=INF;
    		getG1(u,0,trsz);
    		return G;
    	}
    }
    void work(int u,int last,int depth){
    	dis[++cntdis]=depth;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last||vis[v])continue;
    		work(v,u,depth+e[i].w);
    	}
    }
    int solve(int u,int kk){
    	cntdis=0;
    	work(u,0,0);
    	sort(dis+1,dis+cntdis+1);
    	int ans=0;
    	pair<int*,int*> tmp;
    	for(int i=1;i<=cntdis;i++){
    		tmp=equal_range(dis+i+1,dis+cntdis+1,kk-dis[i]);
    		ans+=tmp.second-tmp.first;
    	}
    	return ans;
    }
    bool dfs(int g){
    	int ans=solve(g,k);
    	vis[g]=1;
    	for(int i=head[g];i;i=e[i].next){
    		int v=e[i].to;
    		if(vis[v])continue;
    		ans-=solve(v,k-(e[i].w<<1));
    	}
    	if(ans)return 1;
    	for(int i=head[g];i;i=e[i].next){
    		int v=e[i].to;
    		if(vis[v])continue;
    		int gg=GG::getG(v);
    		if(dfs(gg))return 1;
    	}
    	return 0;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<n;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w),add(v,u,w);
    	}
    	int g=GG::getG(1);
    	while(m--){
    		scanf("%d",&k);
    		for(int i=1;i<=n;i++)vis[i]=0;
    		puts(dfs(g)?"AYE":"NAY");
    	}
    	return 0;
    }
    

    DSU on tree

    例:Codeforces 600E

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100003;
    struct edge{int to,next;}e[maxn<<1];
    int head[maxn],cnte;
    void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
    int n,a[maxn],sz[maxn],son[maxn],buc[maxn],mxcnt;
    long long sum,ANS[maxn];
    void init(int u,int last){
    	sz[u]=1;
    	int res=0;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last)continue;
    		init(v,u);
    		sz[u]+=sz[v];
    		if(sz[v]>res)res=sz[v],son[u]=v;
    	}
    }
    void add(int u,int last,int heavy){
    	buc[a[u]]++;
    	if(buc[a[u]]>mxcnt)mxcnt=buc[a[u]],sum=a[u];
    	else if(buc[a[u]]==mxcnt)sum+=a[u];
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last||v==heavy)continue;
    		add(v,u,heavy);
    	}
    }
    void del(int u,int last){
    	buc[a[u]]--;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last)continue;
    		del(v,u);
    	}
    }
    void dfs(int u,int last,bool keep){
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last||v==son[u])continue;
    		dfs(v,u,0);
    	}
    	if(son[u])dfs(son[u],u,1);
    	add(u,last,son[u]);
    	ANS[u]=sum;
    	if(!keep){
    		mxcnt=sum=0;
    		del(u,last);
    	}
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",a+i);
    	for(int i=1;i<n;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		add(u,v),add(v,u);
    	}
    	init(1,0);
    	dfs(1,0,0);
    	for(int i=1;i<=n;i++)printf("%lld ",ANS[i]);
    	return 0;
    }
    

    Data structures

    Heavy-light-decomposition

    namespace SEG{
        struct node{
            long long sum,z;
        }t[maxn<<2];
        void pushdown(int p,int l,int r){
            if(l==r){t[p].z=0;return;}
            if(t[p].z){
                int mid=(l+r)>>1;
                PlusEqual(t[p<<1].sum,L(t[p].z*(mid-l+1)));
                PlusEqual(t[p<<1|1].sum,L(t[p].z*(r-mid)));
                PlusEqual(t[p<<1].z,t[p].z);
                PlusEqual(t[p<<1|1].z,t[p].z);
                t[p].z=0;
            }
        }
        void pushup(int p,int l,int r){
            t[p].sum=L(t[p<<1].sum+t[p<<1|1].sum);
        }
        void build(int p,int l,int r){
            t[p].z=0;
            if(l==r){
                t[p].sum=a[num[l]];
                return;
            }
            int mid=(l+r)>>1;
            build(p<<1,l,mid);
            build(p<<1|1,mid+1,r);
            pushup(p,l,r);
        }
        void change(int p,int l,int r,int pos,long long k){
            pushdown(p,l,r);
            if(l==r){
                PlusEqual(t[p].sum,k);
                return;
            }
            int mid=(l+r)>>1;
            if(pos<=mid)change(p<<1,l,mid,pos,k);
            else change(p<<1|1,mid+1,r,pos,k);
            pushup(p,l,r);
        }
        void change(int p,int l,int r,int seg_l,int seg_r,long long k){
            pushdown(p,l,r);
            if(seg_l<=l&&r<=seg_r){
                PlusEqual(t[p].sum,L(k*(r-l+1)));
                t[p].z=k;
                return;
            }
            int mid=(l+r)>>1;
            if(seg_l<=mid)change(p<<1,l,mid,seg_l,seg_r,k);
            if(seg_r>mid)change(p<<1|1,mid+1,r,seg_l,seg_r,k);
            pushup(p,l,r);
        }
        long long query(int p,int l,int r,int seg_l,int seg_r){
            pushdown(p,l,r);
            if(seg_l<=l&&r<=seg_r){
                return t[p].sum;
            }
            int mid=(l+r)>>1;
            long long ret=0;
            if(seg_l<=mid)PlusEqual(ret,query(p<<1,l,mid,seg_l,seg_r));
            if(seg_r>mid)PlusEqual(ret,query(p<<1|1,mid+1,r,seg_l,seg_r));
            return ret;
        }
    }
    
    void initdep(int u,int last,int depth){
        fa[u]=last;
        dep[u]=depth;
        sz[u]=1;
        int mxsz=0;
        for(int i=head[u];~i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u])continue;
            initdep(v,u,depth+1);
            sz[u]+=sz[v];
            if(sz[v]>mxsz)mxsz=sz[v],son[u]=v;
        }
    }
    void initdfn(int u,int tp){
        dfn[u]=++cntdfn;
        num[cntdfn]=u;
        top[u]=tp;
        if(son[u]){
            initdfn(son[u],tp);
            for(int i=head[u];~i;i=e[i].next){
                int v=e[i].to;
                if(v==fa[u]||v==son[u])continue;
                initdfn(v,v);
            }
        }
        rig[u]=cntdfn;
    }
    void change(int u,long long w){
        SEG::change(1,1,n,dfn[u],w);
    }
    void change(int x,int y,long long w){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            SEG::change(1,1,n,dfn[top[x]],dfn[x],w);
            x=fa[top[x]];
        }
        if(dep[x]<dep[y])swap(x,y);
        SEG::change(1,1,n,dfn[y],dfn[x],w);
    }
    void changesub(int u,long long w){
        SEG::change(1,1,n,dfn[u],rig[u],w);
    }
    long long query(int x,int y){
        long long ans=0;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            PlusEqual(ans,SEG::query(1,1,n,dfn[top[x]],dfn[x]));
            x=fa[top[x]];
        }
        if(dep[x]<dep[y])swap(x,y);
        PlusEqual(ans,SEG::query(1,1,n,dfn[y],dfn[x]));
        return ans;
    }
    long long querysub(int x){
        return SEG::query(1,1,n,dfn[x],rig[x]);
    }
    

    LCT

    例:QTREE

    #include<stdio.h>
    #define maxn 20003
    void swap(int *x,int *y){int t=*x;*x=*y;*y=t;}
    int max(int x,int y){return x>y?x:y;}
    
    struct node{
        int val,mx,fa,son[2],z;
    }t[maxn];
    int isroot(int p){return t[t[p].fa].son[0]!=p&&t[t[p].fa].son[1]!=p;}
    int chk(int p){return t[t[p].fa].son[1]==p;}
    void reverse(int p){if(p==0)return;swap(&t[p].son[0],&t[p].son[1]);t[p].z^=1;}
    void pushup(int p){t[p].mx=max(max(t[t[p].son[0]].mx,t[t[p].son[1]].mx),t[p].val);}
    void pushdown(int p){
        if(t[p].z){
            reverse(t[p].son[0]);
            reverse(t[p].son[1]);
            t[p].z=0;
        }
    }
    void pushall(int p){if(!isroot(p))pushall(t[p].fa);pushdown(p);}
    void rotate(int p){
        int q=t[p].fa,r=t[q].fa,k=chk(p),s=t[p].son[!k];
        t[q].son[k]=s,t[s].fa=q;
        if(!isroot(q))t[r].son[chk(q)]=p;
        t[p].fa=r;
        t[p].son[!k]=q,t[q].fa=p;
        pushup(q);
        pushup(p);
    }
    void splay(int p){
        pushall(p);
        while(!isroot(p)){
            int q=t[p].fa;
            if(!isroot(q)){
                if(chk(p)==chk(q))rotate(q);
                else rotate(p);
            }
            rotate(p);
        }
    }
    void new_node(int p,int fa,int k){t[p].fa=fa,t[p].mx=t[p].val=k;}
    
    void access(int x){for(int y=0;x;y=x,x=t[x].fa)splay(x),t[x].son[1]=y,pushup(x);}
    void change(int x,int k){splay(x),t[x].val=k,pushup(x);}
    void makeroot(int x){access(x),splay(x),reverse(x);}
    int query(int x,int y){makeroot(x),access(y),splay(y);return t[y].mx;}
    
    struct edge{int to,next;}e[maxn<<1];
    int head[maxn],cnte;
    void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
    int n,a[maxn],ed[maxn];
    void dfs(int u,int last){
        new_node(u,last,a[u]);
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==last)continue;
            dfs(v,u);
        }
    }
    void init(){
        for(int i=0;i<=(n<<1);i++)t[i].val=t[i].mx=t[i].fa=t[i].son[0]=t[i].son[1]=t[i].z=head[i]=a[i]=ed[i]=0;
        cnte=0;
    }
    char mo[13];
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            init();
            for(int i=1;i<n;i++){
                int u,v,w;
                scanf("%d",&u),scanf("%d",&v),scanf("%d",&w);
                add(u,i+n),add(i+n,u),add(i+n,v),add(v,i+n);
                ed[i]=i+n;
                a[i+n]=w;
            }
            n=n+n-1;
            dfs(1,0);
            while(scanf("%s",mo),*mo!='D'){
                int x,y;
                scanf("%d",&x),scanf("%d",&y);
                if(*mo=='Q'){
                    printf("%d
    ",query(x,y));
                }
                else{
                    change(ed[x],y);
                }
            }
        }
        return 0;
    }
    

    QTREE7

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100003,INF=0x3f3f3f3f;
    template<typename tp>
    void read(tp& x){
    	x=0;
    	char c=getchar();
    	bool sgn=0;
    	while((c<'0'||c>'9')&&c!='-')c=getchar();
    	if(c=='-')sgn=1,c=getchar();
    	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    	if(sgn)x=-x;
    }
    template<typename tp>
    void write(tp x){
    	if(x<0)putchar('-'),write(-x);
    	else{
    		if(x>=10)write(x/10);
    		putchar(x%10+'0');
    	}
    }
    
    struct edge{int to,next;}e[maxn<<1];
    int head[maxn],cnte;
    void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
    int n,fa[maxn],val[maxn],a[maxn];
    
    struct LCT{
    	struct node{
    		int mx,fa,son[2];
    	};node t[maxn];
    	multiset<int,greater<int> > light[maxn];
    	bool isroot(int p){return t[t[p].fa].son[0]!=p&&t[t[p].fa].son[1]!=p;}
    	bool chk(int p){return t[t[p].fa].son[1]==p;}
    	void pushup(int p){
    		t[p].mx=max(max(max(t[t[p].son[0]].mx,t[t[p].son[1]].mx),a[p]),light[p].empty()?-INF:*light[p].begin());
    	}
    	void rotate(int p){
    		int q=t[p].fa,r=t[q].fa,k=chk(p),s=t[p].son[!k];
    		t[q].son[k]=s,t[s].fa=q;
    		if(!isroot(q))t[r].son[chk(q)]=p;
    		t[p].fa=r;
    		t[p].son[!k]=q,t[q].fa=p;
    		pushup(q);
    		pushup(p);
    	}
    	void splay(int p){
    		while(!isroot(p)){
    			int q=t[p].fa,r=t[q].fa;
    			if(!isroot(q)){
    				if(chk(p)==chk(q))rotate(q);
    				else rotate(p);
    			}
    			rotate(p);
    		}
    	}
    	int find(int p){
    		while(t[p].son[0])p=t[p].son[0];
    		splay(p);
    		return p;
    	}
    
    	void access(int x){
    		for(int y=0;x;y=x,x=t[x].fa){
    			splay(x);
    			light[x].insert(t[t[x].son[1]].mx);
    			t[x].son[1]=y;
    			light[x].erase(light[x].lower_bound(t[t[x].son[1]].mx));
    			pushup(x);
    		}
    	}
    	void link(int x){
    		if(fa[x]==0)return;
    		access(fa[x]),splay(fa[x]),splay(x);
    		t[x].fa=fa[x];
    		light[fa[x]].insert(t[x].mx);
    		pushup(fa[x]);
    	}
    	void cut(int x){
    		if(fa[x]==0)return;
    		access(x),splay(x);
    		t[x].son[0]=t[t[x].son[0]].fa=0;
    		pushup(x);
    	}
    	int query(int x){
    		access(x),splay(x);
    		int tmp=find(x);
    		return val[tmp]==val[x]?t[tmp].mx:t[t[tmp].son[1]].mx;
    	}
    
    	void init(int n){for(int i=0;i<=n;i++)t[i].mx=-INF,t[i].fa=t[i].son[0]=t[i].son[1]=0;}
    }tree[2];
    
    void dfs(int u,int last){
    	fa[u]=last;
    	for(int i=head[u];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==last)continue;
    		dfs(v,u);
    	}
    }
    
    int main(){
    	read(n);
    	tree[0].init(n);
    	tree[1].init(n);
    	for(int i=0;i<=n;i++)a[i]=-INF;
    	for(int i=1;i<n;i++){
    		int u,v;
    		read(u),read(v);
    		add(u,v),add(v,u);
    	}
    	for(int i=1;i<=n;i++)read(val[i]);
    	for(int i=1;i<=n;i++)read(a[i]),tree[0].t[i].mx=tree[1].t[i].mx=a[i];
    	dfs(1,0);
    	for(int i=1;i<=n;i++)tree[val[i]].link(i);
    	int Q;
    	read(Q);
    	while(Q--){
    		int mo,x;
    		read(mo),read(x);
    		if(mo==1){
    			tree[val[x]].cut(x);
    			val[x]^=1;
    			tree[val[x]].link(x);
    		}
    		else if(mo==2){
    			int y;
    			read(y);
    			tree[0].access(x),tree[0].splay(x),tree[1].access(x),tree[1].splay(x);
    			a[x]=y;
    			tree[0].pushup(x),tree[1].pushup(x);
    		}
    		else{
    			write(tree[val[x]].query(x)),putchar('
    ');
    		}
    	}
    	return 0;
    }
    

    【模板】动态树

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=300003;
    template<typename tp>
    void read(tp& x){
        x=0;
        char c=getchar();
        bool sgn=0;
        while((c<'0'||c>'9')&&c!='-')c=getchar();
        if(c=='-')sgn=1,c=getchar();
        while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
        if(sgn)x=-x;
    }
    template<typename tp>
    void write(tp x){
        if(x<0)putchar('-'),write(-x);
        else{
            if(x>=10)write(x/10);
            putchar(x%10+'0');
        }
    }
    
    int n,a[maxn];
    
    struct node{
        int sum,fa,son[2];
        bool z;
    }t[maxn];
    bool isroot(int p){return t[t[p].fa].son[0]!=p&&t[t[p].fa].son[1]!=p;}
    bool chk(int p){return t[t[p].fa].son[1]==p;}
    void reverse(int p){if(p==0)return;swap(t[p].son[0],t[p].son[1]);t[p].z^=1;}
    void pushup(int p){
        t[p].sum=t[t[p].son[0]].sum^t[t[p].son[1]].sum^a[p];
    }
    void pushdown(int p){
        if(t[p].z){
            reverse(t[p].son[0]);
            reverse(t[p].son[1]);
            t[p].z=0;
        }
    }
    void pushall(int p){if(!isroot(p))pushall(t[p].fa);pushdown(p);}
    void rotate(int p){
        int q=t[p].fa,r=t[q].fa,k=chk(p),s=t[p].son[!k];
        t[q].son[k]=s,t[s].fa=q;
        if(!isroot(q))t[r].son[chk(q)]=p;
        t[p].fa=r;
        t[p].son[!k]=q,t[q].fa=p;
        pushup(q);
        pushup(p);
    }
    void splay(int p){
        pushall(p);
        while(!isroot(p)){
            int q=t[p].fa;
            if(!isroot(q)){
                if(chk(p)==chk(q))rotate(q);
                else rotate(p);
            }
            rotate(p);
        }
    }
    
    void access(int x){for(int y=0;x;y=x,x=t[x].fa)splay(x),t[x].son[1]=y,pushup(x);}
    void change(int x,int k){splay(x),a[x]=k,pushup(x);}
    void makeroot(int x){access(x),splay(x),reverse(x);}
    int findroot(int x){
        access(x),splay(x);
        while(t[x].son[0])pushdown(x),x=t[x].son[0];
        splay(x);
        return x;
    }
    int query(int x,int y){makeroot(x),access(y),splay(y);return t[y].sum;}
    bool link(int x,int y){
        makeroot(x);
        if(findroot(y)==x)return 0;
        t[x].fa=y;
        return 1;
    }
    bool cut(int x,int y){
        makeroot(x);
        if(findroot(y)!=x||t[y].fa!=x||t[y].son[0])return 0;
        t[y].fa=t[x].son[1]=0;
        pushup(x);
        return 1;
    }
    
    int main(){
        int Q;
        read(n),read(Q);
        for(int i=1;i<=n;i++)read(a[i]),t[i].sum=a[i];
        while(Q--){
            int mo,x,y;
            read(mo),read(x),read(y);
            if(mo==0){
                write(query(x,y)),putchar('
    ');
            }
            else if(mo==1){
                link(x,y);
            }
            else if(mo==2){
                cut(x,y);
            }
            else{
                change(x,y);
            }
        }
        return 0;
    }
    

    单调队列

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1000003;
    int a[maxn],n,k,q[maxn],qhead,qtail;
    int main(){
    	scanf("%d%d",&n,&k);
    	for(int i=1;i<=n;i++)scanf("%d",a+i);
    	qhead=1,qtail=0;
    	for(int i=1;i<=n;i++){
    		while(qhead<=qtail&&a[i]<=a[q[qtail]])qtail--;
    		q[++qtail]=i;
    		while(qhead<=qtail&&i-q[qhead]>=k)qhead++;
    		if(i>=k)printf("%d ",a[q[qhead]]);
    	}
    	puts("");
    	qhead=1,qtail=0;
    	for(int i=1;i<=n;i++){
    		while(qhead<=qtail&&a[i]>=a[q[qtail]])qtail--;
    		q[++qtail]=i;
    		while(qhead<=qtail&&i-q[qhead]>=k)qhead++;
    		if(i>=k)printf("%d ",a[q[qhead]]);
    	}
    	return 0;
    }
    

    Heap

    template<typename tp>
    class heap{
    	tp h[1000002];
        int cnt;
    	public:
    	heap():cnt(0){}
    	void push(const tp &x){
    		h[++cnt]=x;
    		int p=cnt;
    		while(p>=2&&h[p>>1]>h[p]){
    			swap(h[p>>1],h[p]);
    			p>>=1;
    		}
    	}
    	void pop(){
    		swap(h[1],h[cnt]);
    		cnt--;
    		int p=1;
    		while((p<<1)<=cnt){
    			p<<=1;
    			if(p<cnt&&h[p|1]<h[p])p|=1;
    			if(h[p]<h[p>>1])swap(h[p],h[p>>1]);
    			else break;
    		}
    	}
    	const tp &top(){
    		return h[1];
    	}
    };
    

    单调栈

    for(int i=1;i<=n;i++){
        int top=0;
        for(int j=1;j<=n;j++){
            if(b[i][j])a[j]=i;
            int tot=1;
            while(top&&a[j]>=a[stk[top]]){
                D tmp=at(a[stk[top]]+1,stk[top]-cnt[top]+1,i,j-1);
                if(tmp>ans){
                    ans=tmp;
                    x1=a[stk[top]]+1,y1=stk[top]-cnt[top]+1,x2=i,y2=j-1;
                }
                tot+=cnt[top];
                top--;
            }
            stk[++top]=j;
            cnt[top]=tot;
        }
        while(top){
            D tmp=at(a[stk[top]]+1,stk[top]-cnt[top]+1,i,n);
            if(tmp>ans){
                ans=tmp;
                x1=a[stk[top]]+1,y1=stk[top]-cnt[top]+1,x2=i,y2=n;
            }
            top--;
        }
    }
    

    左偏树

    int new_node(int val){
    	t[++cnt].val=val;
    	return cnt;
    }
    void merge(int &p,int x,int y){
    	if(x==0||y==0){p=x+y;return;}
    	if(a[t[x].val]!=a[t[y].val]?a[t[x].val]>a[t[y].val]:t[x].val>t[y].val)swap(x,y);
    	p=x;
    	merge(R(p),R(x),y);
    	if(dis[L(p)]<dis[R(p)])swap(L(p),R(p));
    	dis[p]=dis[R(p)]+1;
    }
    void pop(int &p){
    	merge(p,L(p),R(p));
    }
    

    DSU

    int f[maxn];
    int find(int x){return x!=f[x]?f[x]=find(f[x]):x;}
    void Union(int x,int y){int fx=find(x),fy=find(y);if(fx!=fy)f[fx]=fy;}
    bool same(int x,int y){return find(x)==find(y);}
    

    ST algorithm

    void init(){
    	for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
    	for(int len=1;(1<<len)<=n;len++){
    		for(int i=1;i+(1<<len)-1<=n;i++){
    			st[i][len]=max(st[i][len-1],st[i+(1<<(len-1))][len-1]);
    		}
    	}
    }
    int query(int l,int r){
    	int tmp=lg[r-l+1];
    	return max(st[l][tmp],st[r-(1<<tmp)+1]fe[tmp]);
    }
    

    Fenwick tree

    int t[maxn];
    void add(int pos,int k){while(pos<=n)t[pos]+=k,pos+=pos&-pos;}
    int query(int pos){int ret=0;while(pos)ret+=t[pos],pos-=pos&-pos;return ret;}
    

    Segment tree

    merge

    void merge(int &p,int q){
    	if(!p||!q){p|=q;return;}
        cnt++;
        sz[cnt]=sz[p]+sz[q];
        p=cnt;
    	merge(L[p],L[q]);
    	merge(R[p],R[q]);
    }
    

    树套树

    #include<bits/stdc++.h>
    #define L(p) t[p].son[0]
    #define R(p) t[p].son[1]
    using namespace std;
    const int maxn=100005,maxv=100000000,INF=2147483647;
    struct treap_node{
    	int val,son[2],sz;
    }t[4000005];
    int cnt,n,a[maxn];
    struct TREAP{
    	int root;
    	TREAP():root(0){}
    	void O(int p){
    		if(p==0)return;
    		O(L(p));
    		printf("%d ",t[p].val);
    		O(R(p));
    	}
    	void DEBUG(){
    		printf("###### DEBUG root:%d ######
    ",root);
    		O(root);
    		printf("
    ######  ######
    ");
    	}
    	void pushup(int p){t[p].sz=t[L(p)].sz+t[R(p)].sz+1;}
    	void split(int p,int k,int &x,int &y){
    		if(p==0){x=y=0;return;}
    		if(t[p].val<=k){
    			x=p;
    			split(R(p),k,R(p),y);
    		}
    		else{
    			y=p;
    			split(L(p),k,x,L(p));
    		}
    		pushup(p);
    	}
    	void merge(int &p,int x,int y){
    		if(x==0||y==0){p=x+y;return;}
    		if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
    			merge(R(x),R(x),y);
    			pushup(x);
    			p=x;
    		}
    		else{
    			merge(L(y),x,L(y));
    			pushup(y);
    			p=y;
    		}
    	}
    	int new_node(int k){
    		cnt++;
    		t[cnt].val=k;
    		t[cnt].sz=1;
    		return cnt;
    	}
    	void insert(int k){
    		int p,x,y;
    		split(root,k,x,y);
    		p=new_node(k);
    		merge(p,x,p);
    		merge(root,p,y);
    	}
    	void erase(int k){
    		int x,y,z;
    		split(root,k,x,y);
    		split(x,k-1,z,x);
    		merge(z,z,L(x));
    		merge(y,R(x),y);
    		merge(root,z,y);
    	}
    	int rnk(int k){
    		int x,y;
    		split(root,k-1,x,y);
    		int ret=t[x].sz+1;
    		merge(root,x,y);
    		return ret;
    	}
    	int kth(int p,int k){
    		while(1){
    			if(k<=t[L(p)].sz)p=L(p);
    			else{
    				k-=(t[L(p)].sz+1);
    				if(k<=0)return p;
    				p=R(p);
    			}
    		}
    	}
    	int pre(int k){
    		int x,y;
    		split(root,k-1,x,y);
    		if(t[x].sz==0)return -INF;
    		int ret=kth(x,t[x].sz);
    		merge(root,x,y);
    		return t[ret].val;
    	}
    	int nxt(int k){
    		int x,y;
    		split(root,k,x,y);
    		if(t[y].sz==0)return INF;
    		int ret=kth(y,1);
    		merge(root,x,y);
    		return t[ret].val;
    	}
    };
    struct SEG{
    	struct seg_node{
    		TREAP tr;
    	}t[maxn<<2];
    	void build(int p,int l,int r){
    		for(int i=l;i<=r;i++)t[p].tr.insert(a[i]);
    		if(l==r)return;
    		int mid=(l+r)>>1;
    		build(p<<1,l,mid);
    		build(p<<1|1,mid+1,r);
    	}
    	void change(int p,int l,int r,int pos,int k){
    		t[p].tr.erase(a[pos]);
    		t[p].tr.insert(k);
    		if(l==r)return;
    		int mid=(l+r)>>1;
    		if(pos<=mid)change(p<<1,l,mid,pos,k);
    		else change(p<<1|1,mid+1,r,pos,k);
    	}
    	int _rnk(int p,int l,int r,int seg_l,int seg_r,int k){
    		if(seg_l<=l&&r<=seg_r)return t[p].tr.rnk(k)-1;
    		int mid=(l+r)>>1,ret=0;
    		if(seg_l<=mid)ret+=_rnk(p<<1,l,mid,seg_l,seg_r,k);
    		if(seg_r>mid)ret+=_rnk(p<<1|1,mid+1,r,seg_l,seg_r,k);
    		return ret;
    	}
    	int rnk(int seg_l,int seg_r,int k){
    		return _rnk(1,1,n,seg_l,seg_r,k)+1;
    	}
    	int kth(int seg_l,int seg_r,int k){
    		int l=0,r=maxv,mid,ans=-1;
    		while(l<=r){
    			mid=(l+r)>>1;
    			if(rnk(seg_l,seg_r,mid)<=k)ans=mid,l=mid+1;
    			else r=mid-1;
    		}
    		return ans;
    	}
    	int pre(int p,int l,int r,int seg_l,int seg_r,int k){
    		if(seg_l<=l&&r<=seg_r)return t[p].tr.pre(k);
    		int mid=(l+r)>>1,ret=-INF;
    		if(seg_l<=mid)ret=max(ret,pre(p<<1,l,mid,seg_l,seg_r,k));
    		if(seg_r>mid)ret=max(ret,pre(p<<1|1,mid+1,r,seg_l,seg_r,k));
    		return ret;
    	}
    	int nxt(int p,int l,int r,int seg_l,int seg_r,int k){
    		if(seg_l<=l&&r<=seg_r)return t[p].tr.nxt(k);
    		int mid=(l+r)>>1,ret=INF;
    		if(seg_l<=mid)ret=min(ret,nxt(p<<1,l,mid,seg_l,seg_r,k));
    		if(seg_r>mid)ret=min(ret,nxt(p<<1|1,mid+1,r,seg_l,seg_r,k));
    		return ret;
    	}
    }seg;
    int main(){
    	srand(19260817);
    	int Q,mo,x,y,z;
    	scanf("%d%d",&n,&Q);
    	for(int i=1;i<=n;i++)scanf("%d",a+i);
    	seg.build(1,1,n);
    	while(Q--){
    		scanf("%d%d%d",&mo,&x,&y);
    		switch(mo){
    			case 1:scanf("%d",&z),printf("%d
    ",seg.rnk(x,y,z));break;
    			case 2:scanf("%d",&z),printf("%d
    ",seg.kth(x,y,z));break;
    			case 3:seg.change(1,1,n,x,y),a[x]=y;break;
    			case 4:scanf("%d",&z),printf("%d
    ",seg.pre(1,1,n,x,y,z));break;
    			case 5:scanf("%d",&z),printf("%d
    ",seg.nxt(1,1,n,x,y,z));break;
    		}
    	}
    	return 0;
    }
    

    Treap

    维护权值

    #include<bits/stdc++.h>
    #define maxn 100003
    using namespace std;
    struct node{
    	int val,son[2],sz;
    }t[maxn];
    int cnt,root;
    void pushup(int p){t[p].sz=t[t[p].son[0]].sz+t[t[p].son[1]].sz+1;}
    void split(int p,int k,int &x,int &y){
    	if(p==0){x=y=0;return;}
    	if(t[p].val<=k){
    		x=p;
    		split(t[p].son[1],k,t[p].son[1],y);
    	}
    	else{
    		y=p;
    		split(t[p].son[0],k,x,t[p].son[0]);
    	}
    	pushup(p);
    }
    void merge(int &p,int x,int y){
    	if(x==0||y==0){p=x+y;return;}
    	if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
    		merge(t[x].son[1],t[x].son[1],y);
    		pushup(x);
    		p=x;
    	}
    	else{
    		merge(t[y].son[0],x,t[y].son[0]);
    		pushup(y);
    		p=y;
    	}
    }
    int new_node(int k){
    	cnt++;
    	t[cnt].val=k;
    	t[cnt].sz=1;
    	return cnt;
    }
    void insert(int k){
    	int p,x,y;
    	split(root,k,x,y);
    	p=new_node(k);
    	merge(p,x,p);
    	merge(root,p,y);
    }
    void erase(int k){
    	int x,y,z;
    	split(root,k,x,y);
    	split(x,k-1,z,x);
    	merge(z,z,t[x].son[0]);
    	merge(y,t[x].son[1],y);
    	merge(root,z,y);
    }
    int rnk(int k){
    	int x,y;
    	split(root,k-1,x,y);
    	int ret=t[x].sz+1;
    	merge(root,x,y);
    	return ret;
    }
    int kth(int p,int k){
    	while(1){
    		if(k<=t[t[p].son[0]].sz)p=t[p].son[0];
    		else{
    			k-=(t[t[p].son[0]].sz+1);
    			if(k<=0)return p;
    			p=t[p].son[1];
    		}
    	}
    }
    int pre(int k){
    	int x,y;
    	split(root,k-1,x,y);
    	int ret=kth(x,t[x].sz);
    	merge(root,x,y);
    	return ret;
    }
    int nxt(int k){
    	int x,y;
    	split(root,k,x,y);
    	int ret=kth(y,1);
    	merge(root,x,y);
    	return ret;
    }
    int main(){
    	srand(19260817);
    	int Q;
    	scanf("%d",&Q);
    	while(Q--){
    		int mo,x;
    		scanf("%d%d",&mo,&x);
    		switch(mo){
    			case 1:insert(x);break;
    			case 2:erase(x);break;
    			case 3:printf("%d
    ",rnk(x));break;
    			case 4:printf("%d
    ",t[kth(root,x)].val);break;
    			case 5:printf("%d
    ",t[pre(x)].val);break;
    			case 6:printf("%d
    ",t[nxt(x)].val);break;
    		}
    	}
    	return 0;
    }
    

    维护序列

    #include<bits/stdc++.h>
    #define L(p) t[p].son0
    #define R(p) t[p].son1
    using namespace std;
    const int maxn=100003;
    struct node{
    	int son0,son1,sz;
    	bool z;
    }t[maxn];
    int cnt,root;
    void pushup(int p){t[p].sz=t[L(p)].sz+t[R(p)].sz+1;}
    void solve(int p){if(p)swap(L(p),R(p)),t[p].z^=1;}
    void pushdown(int p){
    	if(t[p].z){
    		solve(L(p)),solve(R(p));
    		t[p].z=0;
    	}
    }
    void output(int p){
    	if(p==0)return;
    	pushdown(p);
    	output(L(p));
    	printf("%d ",p);
    	output(R(p));
    }
    void O(int p=root){
    	output(p);
    	puts("");
    }
    void split(int p,int k,int &x,int &y){
    	if(p==0){x=y=0;return;}
    	pushdown(p);
    	if(t[L(p)].sz+1<=k){
    		x=p;
    		split(R(p),k-t[L(p)].sz-1,R(p),y);
    	}
    	else{
    		y=p;
    		split(L(p),k,x,L(p));
    	}
    	pushup(p);
    }
    void merge(int &p,int x,int y){
    	if(x==0||y==0){p=x+y;return;}
    	if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
    		pushdown(x);
    		merge(R(x),R(x),y);
    		pushup(x);
    		p=x;
    	}
    	else{
    		pushdown(y);
    		merge(L(y),x,L(y));
    		pushup(y);
    		p=y;
    	}
    }
    void build(int &p,int l,int r){
    	if(l>r)return;
    	p=(l+r)>>1;
    	build(L(p),l,p-1);
    	build(R(p),p+1,r);
    	pushup(p);
    }
    void reverse(int l,int r){
    	int x,y,z;
    	split(root,l-1,x,y);
    	split(y,r-l+1,y,z);
    	solve(y);
    	merge(y,x,y);
    	merge(root,y,z);
    }
    int main(){
    	srand(19260817);
    	int n,Q;
    	scanf("%d%d",&n,&Q);
    	build(root,1,n);
    	while(Q--){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		reverse(x,y);
    	}
    	O();
    	return 0;
    }
    

    persistent

    #include<bits/stdc++.h>
    #define L(p) t[p].son[0]
    #define R(p) t[p].son[1]
    using namespace std;
    namespace FASTIO{...}
    const int maxn=200003;
    struct node{
    	int val,son[2],sz;
    	long long sum;
    	bool z;
    }t[20000003];
    int cnt,root[maxn];
    int new_node(int k){
    	cnt++;
    	t[cnt].val=t[cnt].sum=k;
    	t[cnt].sz=1;
    	L(cnt)=R(cnt)=0;
    	return cnt;
    }
    void pushup(int p){
    	t[p].sz=t[L(p)].sz+t[R(p)].sz+1;
    	t[p].sum=t[L(p)].sum+t[R(p)].sum+t[p].val;
    }
    void pushdown(int p){
    	if(t[p].z){
    		int l=0,r=0;
    		if(L(p))t[r=++cnt]=t[L(p)],t[r].z^=1;
    		if(R(p))t[l=++cnt]=t[R(p)],t[l].z^=1;
    		L(p)=l,R(p)=r;
    		t[p].z=0;
    	}
    }
    void output(int p){
    	if(p==0)return;
    	pushdown(p);
    	output(L(p));
    	printf("val:%d sum:%lld son0:%d son1:%d
    ",t[p].val,t[p].sum,t[L(p)].val,t[R(p)].val);
    	output(R(p));
    }
    void O(int p){
    	printf("### O ###
    ");
    	puts("############");
    	output(p);
    	puts("############");
    }
    void split(int p,int k,int &x,int &y){
    	if(p==0){x=y=0;return;}
    	pushdown(p);
    	if(t[L(p)].sz+1<=k){
    		x=++cnt;
    		t[x]=t[p];
    		split(R(p),k-t[L(p)].sz-1,R(x),y);
    		pushup(x);
    	}
    	else{
    		y=++cnt;
    		t[y]=t[p];
    		split(L(p),k,x,L(y));
    		pushup(y);
    	}
    }
    void merge(int &p,int x,int y){
    	if(x==0||y==0){p=x+y;return;}
    	if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
    		pushdown(x);
    		merge(R(x),R(x),y);
    		pushup(x);
    		p=x;
    	}
    	else{
    		pushdown(y);
    		merge(L(y),x,L(y));
    		pushup(y);
    		p=y;
    	}
    }
    void insert(int u,int v,int pos,int k){
    	int x,y;
    	split(root[v],pos,x,y);
    	merge(x,x,new_node(k));
    	merge(root[u],x,y);
    }
    void erase(int u,int v,int pos){
    	int x,y,z;
    	split(root[v],pos-1,x,y);
    	split(y,1,y,z);
    	merge(root[u],x,z);
    }
    void reverse(int u,int v,int l,int r){
    	int x,y,z;
    	split(root[v],l-1,x,y);
    	split(y,r-l+1,y,z);
    	t[y].z^=1;
    	merge(y,x,y);
    	merge(root[u],y,z);
    }
    long long query(int v,int l,int r){
    	int x,y,z;
    	split(root[v],l-1,x,y);
    	split(y,r-l+1,y,z);
    	long long ret=t[y].sum;
    	merge(y,x,y);
    	merge(root[v],y,z);
    	return ret;
    }
    int main(){
    	srand(19260817);
    	int Q,v,mo;
    	long long x,y,last=0;
    	read(Q);
    	for(int i=1;i<=Q;i++){
    		read(v),read(mo),read(x);
    		root[i]=root[v];
    		x^=last;
    		if(mo==1){
    			read(y);
    			y^=last;
    			insert(i,v,x,y);
    		}
    		if(mo==2){
    			erase(i,v,x);
    		}
    		if(mo==3){
    			read(y);
    			y^=last;
    			reverse(i,v,x,y);
    		}
    		if(mo==4){
    			read(y);
    			y^=last;
    			write(last=query(v,x,y)),pc('
    ');
    		}
    	}
    	flush();
    	return 0;
    }
    

    String

    KMP

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1000003;
    int kmp[maxn];
    char s1[maxn],s2[maxn];
    int main(){
    	scanf("%s%s",s1+1,s2+1);
    	int l1=strlen(s1+1),l2=strlen(s2+1),pos=0;
    	for(int i=2;i<=l2;i++){
    		while(pos&&s2[pos+1]!=s2[i])pos=kmp[pos];
    		if(s2[pos+1]==s2[i])pos++;
    		kmp[i]=pos;
    	}
    	pos=0;
    	for(int i=1;i<=l1;i++){
    		while(pos&&s1[i]!=s2[pos+1])pos=kmp[pos];
    		if(s1[i]==s2[pos+1])pos++;
    		if(pos==l2){
    			printf("%d
    ",i-l2+1);
    			pos=kmp[pos];
    		}
    	}
    	for(int i=1;i<=l2;i++)printf("%d ",kmp[i]);
    	return 0;
    }
    

    Hash

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=10003;
    char s[maxn];
    int n,ha[maxn];
    int hash(){
    	static const int p1=15797,p2=1000000009;
    	int ret=0;
    	for(int i=0;s[i];i++){
    		ret=(1ll*ret*p1+s[i])%p2;
    	}
    	return ret;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",s);
    		ha[i]=hash();
    	}
    	sort(ha+1,ha+n+1);
    	printf("%d",int(unique(ha+1,ha+n+1)-ha-1));
    	return 0;
    }
    

    Suffix array

    #include<bits/stdc++.h>
    #define maxn 1000003
    #define mod 1000000007
    #define O(a) printf(#a": ");for(int j=1;j<=n;j++)printf("%d ",a[j]);puts("")
    #define DEBUG printf("%d:
    ",(int)__LINE__);O(sa);O(rnk);O(tp);O(buc);O(height)
    using namespace std;
    char s[maxn];
    int rnk[maxn],sa[maxn],tp[maxn],buc[maxn],n,m,height[maxn],a[maxn],f[maxn];
    long long sum[maxn];
    void bucsort(){
    	for(int i=1;i<=m;i++)buc[i]=0;
    	for(int i=1;i<=n;i++)buc[rnk[i]]++;
    	for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
    	for(int i=n;i>=1;i--)sa[buc[rnk[tp[i]]]--]=tp[i];
    }
    void sufsort(){
    	m=128;
    	for(int i=1;i<=n;i++)rnk[i]=s[i],tp[i]=i;
    	bucsort();
    	for(int t=1,cnt=0;cnt<n;m=cnt,t<<=1){
    //update tp
    		cnt=0;
    		for(int i=n-t+1;i<=n;i++)tp[++cnt]=i;
    		for(int i=1;i<=n;i++){
    			if(sa[i]>t)tp[++cnt]=sa[i]-t;
    		}
    //update sa
    		bucsort();
    //update rnk
    		for(int i=1;i<=n;i++)tp[i]=rnk[i];
    		rnk[sa[1]]=cnt=1;
    		for(int i=2;i<=n;i++){
    			rnk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+t]==tp[sa[i-1]+t]?cnt:++cnt);
    		}
    	}
    }
    void geth(){
    	int k=0;
    	for(int i=1;i<=n;i++)rnk[sa[i]]=i;
    	for(int i=1;i<=n;i++){
    		if(rnk[i]==1)continue;
    		if(k)k--;
    		int j=sa[rnk[i]-1];
    		while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
    		height[rnk[i]]=k;
    	}
    }
    bool cmp(int x,int y){return height[x]>height[y];}
    int find(int x){return x!=f[x]?f[x]=find(f[x]):f[x];}
    int main(){
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	sufsort(),geth();
    	for(int i=1;i<=n;i++)a[i]=f[i]=i,sum[i]=1;
    	sort(a+1,a+n+1,cmp);
    	long long ans=0;
    	for(int i=n,j=1;i>=1;i--){
    		for(;j<=n&&height[a[j]]==i;j++){
    			int x=find(sa[a[j]-1]),y=find(sa[a[j]]);
    			sum[x]+=sum[y];
    			ans=max(ans,(long long)i*sum[x]);
    			f[y]=x;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    Manacher

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=22000005;
    char t[maxn>>1],s[maxn];
    int p[maxn];
    int main(){
    	scanf("%s",t+1);
    	int N=strlen(t+1),n=0,mid=0,r=0,ans=1;
    	s[++n]=-2,s[++n]=-1;
    	for(int i=1;i<=N;i++)s[++n]=t[i],s[++n]=-1;
    	for(int i=1;i<=n;i++){
    		if(i<=r)p[i]=min(p[(mid<<1)-i],r-i+1);
    		while(s[i+p[i]]==s[i-p[i]])p[i]++;
    		if(i+p[i]-1>r)r=i+p[i]-1,mid=i;
    		ans=max(ans,p[i]);
    	}
    	printf("%d
    ",ans-1);
    	return 0;
    }
    

    Geometry

    const double eps=1e-10,INF=1e17;
    typedef double tp;
    int sgn(tp x){return x<-eps?-1:x>eps;}
    // const double pi=acos(-1);
    struct point{
    	tp x,y;
    	point(){}
    	point(tp _x,tp _y):x(_x),y(_y){}
    	void write()const{printf("%.4lf %.4lf
    ",x,y);}
    	bool operator<(point p)const{return sgn(x-p.x)==0?sgn(y-p.y)<0:sgn(x-p.x)<0;}
    	bool operator==(point p)const{return sgn(x-p.x)==0&&sgn(y-p.y)==0;}
    	point operator+(point p)const{return point(x+p.x,y+p.y);}
    	point operator-(point p)const{return point(x-p.x,y-p.y);}
    	point operator*(tp k)const{return point(x*k,y*k);}
    	double norm()const{return x*x+y*y;}
    	// double abs()const{return sqrt(x*x+y*y);}
    };
    tp dot(point u,point v){return u.x*v.x+u.y*v.y;}
    tp cross(point u,point v){return u.x*v.y-v.x*u.y;}
    double dist(point p1,point p2){return sqrt(double(dot(p1-p2,p1-p2)));}
    
    point inter(point P,point v,point Q,point w){
    	point u=P-Q;
    	if(sgn(cross(v,w))==0){
    		if(sgn(cross(Q-P,v))==0)return point(-INF,-INF); //chong he
    		return point(INF,INF); //ping xing
    	}
    	tp t=cross(w,u)/cross(v,w);
    	return P+v*t; //OK
    }
    
    bool seg_inter(point p1,point p2,point p3,point p4){
    	return min(p1.x,p2.x)<=max(p3.x,p4.x)&&
    	min(p3.x,p4.x)<=max(p1.x,p2.x)&&
    	min(p1.y,p2.y)<=max(p3.y,p4.y)&&
    	min(p3.y,p4.y)<=max(p1.y,p2.y)&&
    	sgn(cross(p2-p1,p3-p1))*sgn(cross(p2-p1,p4-p1))<=0&&
    	sgn(cross(p4-p3,p1-p3))*sgn(cross(p4-p3,p2-p3))<=0;
    }
    bool line_seg_inter(point l1,point l2,point p1,point p2){
    	return sgn(cross(l2-l1,p1-l1))*sgn(cross(l2-l1,p2-l1))<=0;
    }
    
    int stk[maxn],cntcon;
    point con[maxn];
    void convex_hull(point a[],int n){
    	cntcon=0;
    	int top=2;
    	stk[1]=1,stk[2]=2;
    	for(int i=3;i<=n;i++){
    		while(top>1&&cross(a[i]-a[stk[top]],a[stk[top]]-a[stk[top-1]])>0)top--;
    		stk[++top]=i;
    	}
    	for(int i=1;i<top;i++){
    		con[++cntcon]=a[stk[i]];
    	}
    	top=2;
    	stk[1]=1,stk[2]=2;
    	for(int i=3;i<=n;i++){
    		while(top>1&&cross(a[i]-a[stk[top]],a[stk[top]]-a[stk[top-1]])<=0)top--;
    		stk[++top]=i;
    	}
    	for(int i=top;i>1;i--){
    		con[++cntcon]=a[stk[i]];
    	}
    }
    
    double getS(const vector<point> &p){
    	double ans=cross(p[0],p[p.size()-1]);
    	for(int i=1;i<int(p.size());i++)ans+=cross(p[i],p[i-1]);
    	return abs(ans)*0.5;
    }
    
    bool onright(point P,point S,point T){
    	return sgn(cross(T-S,P-S))<0;
    }
    

    Math

    Number theory

    Combinatorics

    Gauss

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=103;
    const double eps=1e-8;
    int n;
    double a[maxn][maxn];
    int sgn(double x){return x<-eps?-1:x>eps;}
    bool gauss(){
        for(int i=1;i<=n;i++){
            int p=i;
            for(int j=i+1;j<=n;j++)if(abs(a[j][i])>abs(a[p][i]))p=j;
            if(p!=i)for(int j=1;j<=n+1;j++)swap(a[i][j],a[p][j]);
            if(sgn(a[i][i])==0){
                puts("No Solution");
                return 0;
            }
            for(int j=i+1;j<=n+1;j++)a[i][j]/=a[i][i];
            a[i][i]=1;
            for(int j=1;j<=n;j++){
                if(i!=j){
                    for(int k=i+1;k<=n+1;k++)a[j][k]-=a[j][i]*a[i][k];
                    a[j][i]=0;
                }
            }
        }
        return 1;
    }
    signed main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n+1;j++){
                scanf("%lf",&a[i][j]);
            }
        }
        if(!gauss())return 0;
        for(int i=1;i<=n;i++)printf("%.2lf
    ",a[i][n+1]);
        return 0;
    }
    

    Linear basis

    #include<bits/stdc++.h>
    using namespace std;
    const int maxlog=51;
    int n;
    long long p[maxlog];
    void insert(long long x){
    	for(int i=maxlog-1;i>=0;i--){
    		if((x>>i)&1){
    			if(p[i]==0){
    				p[i]=x;
    				break;
    			}
    			else x^=p[i];
    		}
    	}
    }
    long long query(){
    	long long ret=0;
    	for(int i=maxlog-1;i>=0;i--){
    		if((ret^p[i])>ret)ret^=p[i];
    	}
    	return ret;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		long long x;
    		scanf("%lld",&x);
    		insert(x);
    	}
    	printf("%lld",query());
    	return 0;
    }
    

    BSGS

    unordered_map<int,int> mp;
    int bsgs(int y,int z){
    	if(z==1)return 0;
    	if(y%mod==0)return -1;
    	mp.clear();
    	int m=sqrt(mod)+1,ji=z;
    	for(int b=0;b<=m;b++){
    		mp[ji]=b;
    		ji=mul(ji,y);
    	}
    	int tmp=qpow(y,m);
    	ji=1;
    	for(int a=1;a<=m;a++){
    		ji=mul(ji,tmp);
    		if(mp.count(ji))return a*m-mp[ji];
    	}
    	return -1;
    }
    
  • 相关阅读:
    js
    原型、原型链、闭包、继承
    js6.22
    js
    js
    在浏览器窗口上添加一个遮罩层
    git使用笔记
    前端开发面试题
    Web Worker
    js实现图片预加载
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/11663963.html
Copyright © 2020-2023  润新知