DaD3zZ’s 模板

对拍

#include<cstdio>
#include<cstdlib>
using namespace std;
int main()
{    int sb=0;
    while(true)
    {    printf("%d\n",++sb);
        system("data.exe > input.in"); //data是数据生成器,input是生成的数据 
        system("std.exe < input.in > std.out"); 
        system("DaD3zZ.exe < input.in > DaD3zZ.out");
        if(system("fc std.out DaD3zZ.out"))break;
    }//std和自己的,和数据生成器均不需要加freopen 
    
}

 BeiYu的高精度

namespace BigNumber{
	static const int	BASE	= 10000; 
	static const int	WIDTH	= 4;  
struct Big {  
	vector<int>		s;
	Big( long long num = 0 )
	{
		*this = num;
	}


	Big operator =( long long num )
	{
		s.clear();
		do
		{
			s.push_back( num % BASE );
			num /= BASE;
		}
		while ( num > 0 );
		return(*this);
	}


	Big operator =( const string & str )
	{
		s.clear();
		int x, len = (str.length() - 1) / WIDTH + 1;
		for ( int i = 0; i < len; i++ )
		{
			int	end	= str.length() - i * WIDTH;
			int	start	= max( 0, end - WIDTH );
			sscanf( str.substr( start, end - start ).c_str(), "%d", &x );
			s.push_back( x );
		}
		return(*this);
	}


	Big operator +( const Big & b ) const
	{
		Big c;
		c.s.clear();
		for ( int i = 0, g = 0;; i++ )
		{
			if ( g == 0 && i >= s.size() && i >= b.s.size() )
				break;
			int x = g;
			if ( i < s.size() )
				x += s[i];
			if ( i < b.s.size() )
				x += b.s[i];
			c.s.push_back( x % BASE );
			g = x / BASE;
		}
		return(c);
	}


	Big operator -( const Big & b ) const
	{
		Big c;
		c.s.clear();
		int i, g, n = s.size(), m = b.s.size();
		for ( i = 0, g = 0; i < n; i++ )
		{
			int x = s[i] - g;
			if ( i < m )
				x -= b.s[i];
			if ( x >= 0 )
				g = 0;
			else {
				g	= 1;
				x	+= BASE;
			}
			c.s.push_back( x );
		}
		i = c.s.size() - 1;
		while ( c.s[i] == 0 && i )
			c.s.pop_back(), i--;
		return(c);
	}


	Big operator *( const Big &b ) const
	{
		Big	c;
		int	i, j, n = s.size(), m = b.s.size(), size = m + n;
		c.s.resize( size, 0 );
		for ( i = 0; i < n; i++ )
			for ( j = 0; j < m; j++ )
				c.s[i + j] += s[i] * b.s[j];
		for ( i = 0; i < size; i++ )
		{
			c.s[i + 1]	+= c.s[i] / BASE;
			c.s[i]		%= BASE;
		}
		i = size - 1;
		while ( c.s[i] == 0 && i )
			c.s.pop_back(), i--;
		return(c);
	}


	Big operator /( const Big & b ) const
	{
		Big	c, f = 0;
		int	n = s.size(), i;
		c.s.resize( n, 0 );
		for ( i = n - 1; i >= 0; i-- )
		{
			f	= f * BASE;
			f.s[0]	= s[i];
			while ( f >= b )
			{
				f -= b;
				c.s[i]++;
			}
		}
		i = n - 1;
		while ( c.s[i] == 0 && i )
			c.s.pop_back(), i--;
		return(c);
	}


	Big operator %( const Big &b ) const
	{
		Big r = *this / b;
		r = *this - r * b;
		return(r);
	}


	Big operator +=( const Big & b )
	{
		*this = *this + b; return(*this);
	}


	Big operator -=( const Big & b )
	{
		*this = *this - b; return(*this);
	}


	Big operator *=( const Big & b )
	{
		*this = *this * b; return(*this);
	}


	Big operator /=( const Big & b )
	{
		*this = *this / b; return(*this);
	}


	Big operator %=( const Big & b )
	{
		*this = *this % b; return(*this);
	}


	bool operator <( const Big & b ) const
	{
		int n = s.size(), m = b.s.size();
		if ( m > n )
			return(1);
		if ( m < n )
			return(0);
		for ( int i = s.size() - 1; i >= 0; i-- )
		{
			if ( s[i] < b.s[i] )
				return(1);
			if ( s[i] > b.s[i] )
				return(0);
		}
		return(0);
	}


	bool operator >( const Big & b ) const
	{
		return(b < *this);
	}


	bool operator >=( const Big & b ) const
	{
		return(!(*this < b) );
	}


	bool operator <=( const Big & b ) const
	{
		return(!(b < *this) );
	}


	bool operator ==( const Big & b ) const
	{
		return(!(*this < b) && !(b < *this) );
	}


	bool operator !=( const Big & b ) const
	{
		return( (*this < b) || (b < *this) );
	}
};
ostream & operator <<( ostream &out, const Big & x )
{
	out << x.s.back();
	for ( int i = x.s.size() - 2; i >= 0; i-- )
	{
		char buf[10];
		sprintf( buf, "%04d", x.s[i] );
		for ( int j = 0; j < strlen( buf ); j++ )
			out << buf[j];
	}
	return(out);
}


istream & operator >>( istream &in, Big & x )
{
	string s;
	if ( !(in >> s) )
		return(in);
	x = s;
	return(in);
}
}using namespace BigNumber;

 

 

数据结构

李超线段树

//BZOJ-1568
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int N,M;
struct LineNode
{
    double k,b; int id;
    LineNode(int x0=0,int y0=0,int x1=0,int y1=0,int ID=0)
        {
            id=ID;
            if (x0==x1) k=0,b=max(y0,y1);
            else k=(double)(y0-y1)/(x0-x1),b=(double)y0-k*x0;
        } 
    double getf(int x) {return k*x+b;}
};
bool cmp(LineNode A,LineNode B,int x)
{
    if (!A.id) return 1;
    return A.getf(x)!=B.getf(x)?A.getf(x)<B.getf(x):A.id<B.id;  //比较值直线A,B在x的值,如果A<B返回1
}
#define maxn 50010
LineNode tree[maxn<<2];
LineNode Query(int now,int l,int r,int x)
{
    if (l==r) return tree[now];
    int mid=(l+r)>>1; LineNode tmp;
    if (x<=mid) tmp=Query(now<<1,l,mid,x);
    else tmp=Query(now<<1|1,mid+1,r,x);
    return cmp(tree[now],tmp,x)?tmp:tree[now];
}
void insert(int now,int l,int r,LineNode x)
{
    if (!tree[now].id) tree[now]=x;
    if (cmp(tree[now],x,l)) swap(tree[now],x);
    if (l==r || tree[now].k==x.k) return;
    int mid=(l+r)>>1; double X=(tree[now].b-x.b)/(x.k-tree[now].k);//求交点,X为交点横坐标,判断下放区间 
    if (X<l || X>r) return;
    if (X<=mid) insert(now<<1,l,mid,tree[now]),tree[now]=x;
    else insert(now<<1|1,mid+1,r,x);
}
void Insert(int now,int l,int r,int L,int R,LineNode x)
{
    if (L<=l && R>=r) {insert(now,l,r,x); return;}
    int mid=(l+r)>>1;
    if (L<=mid) Insert(now<<1,l,mid,L,R,x);
    if (R>mid) Insert(now<<1|1,mid+1,r,L,R,x);
} 
int main()
{
    M=read(); N=50000;
    char opt[15];
    while (M--)
        {    
            scanf("%s",opt);
            if (opt[0]=='P') 
                {
                    double K,B; scanf("%lf%lf",&K,&B);
                    LineNode tmp; tmp.k=B; tmp.b=K-B; tmp.id=1;
                    Insert(1,1,N,1,N,tmp);    
                }
            int x;
            if (opt[0]=='Q') x=read(),printf("%lld\n",(long long)(Query(1,1,N,x).getf(x)/100+1e-8));
        }
    return 0;
}

左偏树

//BZOJ-1367
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define maxn 1000100
long long ans;
int n,data[maxn],root[maxn],L[maxn],R[maxn],cnt[maxn],tot;
struct LeftTreeNode
{
    int sz,son[maxn][2],d[maxn],size[maxn],a[maxn];
//    LeftTreeNode () 
//        {
//            sz=0;memset(son,0,sizeof(son));memset(size,0,sizeof(size));
//            memset(cnt,0,sizeof(cnt));memset(a,0,sizeof(a));memset(d,0,sizeof(d));
//        }
    int Merge(int x,int y)
        {
            if (!x) return y;
            if (!y) return x;
            if (a[x]<a[y]) swap(x,y);
            son[x][1]=Merge(son[x][1],y);
            size[x]=size[son[x][0]]+size[son[x][1]]+1;
            if (d[son[x][1]]>d[son[x][0]]) swap(son[x][0],son[x][1]);
            d[x]=d[son[x][1]]+1;
            return x;
        }
    int Push(int x)
        {
            a[++sz]=x; size[sz]=1;
            son[sz][0]=son[sz][1]=d[sz]=0;
            return sz;
        }
    int Pop(int x) {return Merge(son[x][0],son[x][1]);}
    int Top(int x) {return a[x];}
    int Size(int x) {return size[x];}
}LTHeap;
int main()
{
    n=read();
    for (int i=1; i<=n; i++) data[i]=read()-i;
    for (int i=1; i<=n; i++)
        {
            tot++;
            root[tot]=LTHeap.Push(data[i]); cnt[tot]=1; L[tot]=R[tot]=i;
            while (tot>1 && LTHeap.Top(root[tot])<LTHeap.Top(root[tot-1]))
                {
                    tot--;
                    root[tot]=LTHeap.Merge(root[tot],root[tot+1]); cnt[tot]+=cnt[tot+1]; R[tot]=R[tot+1];
                    while (LTHeap.Size(root[tot])*2>cnt[tot]+1) 
                        root[tot]=LTHeap.Pop(root[tot]);
                }
        }
    for (int i=1; i<=tot; i++)
        for (int j=L[i],top=LTHeap.Top(root[i]); j<=R[i]; j++)
            ans+=abs(data[j]-top);
    printf("%lld\n",ans);
    return 0;
}

树链剖分

//BZOJ-1984
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    return x*f;
}
#define maxn 400010
int id[maxn<<2],va[maxn<<2],uu[maxn],vv[maxn],ww[maxn];
int n;struct data{int next,to,w;}edge[maxn<<1];int head[maxn],cnt;
void add(int u,int v,int w){cnt++;edge[cnt].w=w;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;}
void insert(int u,int v,int w){add(u,v,w); add(v,u,w);}
//--------------------------------------------------------------------------------------
int deep[maxn],fa[maxn],son[maxn],size[maxn],pl[maxn],sz,pr[maxn],top[maxn],pre[maxn];
void dfs_1(int now)
{
    size[now]=1;
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=fa[now])
            {
                fa[edge[i].to]=now;
                deep[edge[i].to]=deep[now]+1;
                dfs_1(edge[i].to);
                if (size[son[now]]<size[edge[i].to]) son[now]=edge[i].to;
                size[now]+=size[edge[i].to];
            }
}
void dfs_2(int now,int chain)
{
    pl[now]=++sz; pre[sz]=now; top[now]=chain;
    if (son[now]) dfs_2(son[now],chain);
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=son[now] && edge[i].to!=fa[now])
            dfs_2(edge[i].to,edge[i].to);
    pr[now]=sz;
}
//--------------------------------------------------------------------------------------
int tree[maxn<<2],delc[maxn<<2],dela[maxn<<2];
inline void update(int now){tree[now]=max(tree[now<<1],tree[now<<1|1]);}
inline void pushdown(int now)
{
    if (delc[now]!=-1)
        {
            int cc=delc[now]; delc[now]=-1;
            delc[now<<1]=cc; dela[now<<1]=0; tree[now<<1]=cc;
            delc[now<<1|1]=cc; dela[now<<1|1]=0; tree[now<<1|1]=cc;
        }
    if (dela[now])
        {
            int aa=dela[now]; dela[now]=0;
            dela[now<<1]+=aa; tree[now<<1]+=aa;
            dela[now<<1|1]+=aa; tree[now<<1|1]+=aa;
        }
}
void build(int now,int l,int r)
{
    delc[now]=-1; dela[now]=0;
    if (l==r) {tree[now]=va[l];return;}
    int mid=(l+r)>>1;
    build(now<<1,l,mid); build(now<<1|1,mid+1,r);
    update(now);
}
void point_change(int now,int l,int r,int loc,int val)
{
    if (l==r) {tree[now]=val;return;}
    int mid=(l+r)>>1;pushdown(now);
    if (loc<=mid) point_change(now<<1,l,mid,loc,val);
    else point_change(now<<1|1,mid+1,r,loc,val);  
    update(now);
}
void segment_change(int now,int l,int r,int L,int R,int val)
{
    if (L<=l && R>=r) {tree[now]=val;delc[now]=val;dela[now]=0;return;}
    int mid=(l+r)>>1;pushdown(now);
    if (L<=mid) segment_change(now<<1,l,mid,L,R,val);
    if (R>mid) segment_change(now<<1|1,mid+1,r,L,R,val);
    update(now);
}
void segment_add(int now,int l,int r,int L,int R,int val)
{
    if (L<=l && R>=r) {tree[now]+=val;dela[now]+=val;return;}
    int mid=(l+r)>>1;pushdown(now);
    if (L<=mid) segment_add(now<<1,l,mid,L,R,val);
    if (R>mid) segment_add(now<<1|1,mid+1,r,L,R,val);
    update(now);
}
int segment_ask(int now,int l,int r,int L,int R)
{
    if (L<=l && R>=r) return tree[now];
    int mid=(l+r)>>1; int ans=0;pushdown(now);
    if (L<=mid) ans=max(segment_ask(now<<1,l,mid,L,R),ans);
    if (R>mid) ans=max(ans,segment_ask(now<<1|1,mid+1,r,L,R));
    return ans;
}
//--------------------------------------------------------------------------------------
void Change(int x,int val)
{
    point_change(1,1,n,pl[id[x]],val);
}
void Cover(int x,int y,int val)
{
    while (top[x]!=top[y])
        {
            if (deep[top[x]]<deep[top[y]]) swap(x,y);
            segment_change(1,1,n,pl[top[x]],pl[x],val);
            x=fa[top[x]];
        }
    if (deep[x]>deep[y]) swap(x,y);
    if (x!=y) segment_change(1,1,n,pl[x]+1,pl[y],val);//这是有别于平常的判断
}
void Add(int x,int y,int val)
{
    while (top[x]!=top[y])
        {
            if (deep[top[x]]<deep[top[y]]) swap(x,y);
            segment_add(1,1,n,pl[top[x]],pl[x],val);
            x=fa[top[x]];
        }
    if (deep[x]>deep[y]) swap(x,y);
    if (x!=y) segment_add(1,1,n,pl[x]+1,pl[y],val);
}
void Max(int x,int y)
{
    int ans=0;
    while (top[x]!=top[y])
        {
            if (deep[top[x]]<deep[top[y]]) swap(x,y);
            ans=max(ans,segment_ask(1,1,n,pl[top[x]],pl[x]));
            x=fa[top[x]];
        }
    if (deep[x]>deep[y]) swap(x,y);
    if (x!=y) ans=max(ans,segment_ask(1,1,n,pl[x]+1,pl[y]));
    printf("%d\n",ans);
}
//--------------------------------------------------------------------------------------
int main()
{
//  freopen("msn.in","r",stdin);
//  freopen("msn.out","w",stdout);
    n=read();
    for (int i=1; i<=n-1; i++)
        uu[i]=read(),vv[i]=read(),ww[i]=read(),insert(uu[i],vv[i],ww[i]);
    dfs_1(1); dfs_2(1,1);
    for (int i=1; i<=n-1; i++)
        if (deep[uu[i]]<deep[vv[i]]) id[i]=vv[i]; else id[i]=uu[i];
    for (int i=1; i<=n-1; i++) va[pl[id[i]]]=ww[i];//边权下放至点,记录所下放的点的id
    build(1,1,n);
    while (true)
        {
            char opt[10]; scanf("%s",opt);if(opt[1]=='t')break;
            int u=read(),v=read(),w;
            switch (opt[1])
                {
                    case 'a': Max(u,v);break;
                    case 'o': w=read();Cover(u,v,w);break;
                    case 'd': w=read();Add(u,v,w);break;
                    case 'h': Change(u,v);break;
                }
        }
    return 0;
}

LinkCutTree

//BZOJ-2594
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define N 100010
#define M 1000010
#define Q 100010
int n,m,q,num=0;
int fa[N+M],son[N+M][2],s[N+M],val[N+M],maxx[N+M];
bool rev[N+M];
//init
int father[N];
inline void init(){for (int i=1; i<=n; i++) father[i]=i;}
inline int find(int x){if (x==father[x]) return x; return father[x]=find(father[x]);}
inline void merge(int x,int y) {int fx=find(x),fy=find(y); if (fx!=fy) father[fx]=fy,num++;}
//bing cha ji
inline bool is_root(int x){return !fa[x] || son[fa[x]][1]!=x&& son[fa[x]][0]!=x;}
inline void rev1(int x){if (!x)return; swap(son[x][0],son[x][1]);rev[x]^=1;}
inline void pb(int x){if (rev[x]) rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;}
inline void update(int x)
{
    maxx[x]=x;
    if (son[x][0]&&val[maxx[x]]<val[maxx[son[x][0]]]) maxx[x]=maxx[son[x][0]];
    if (son[x][1]&&val[maxx[x]]<val[maxx[son[x][1]]]) maxx[x]=maxx[son[x][1]];
}
inline void rotate(int x)
{
    int y=fa[x],w=son[y][1]==x;son[y][w]=son[x][w^1];
    if (son[x][w^1]) fa[son[x][w^1]]=y;
    if (fa[y]) 
        {
            int z=fa[y];if (son[z][0]==y) son[z][0]=x;
                        else if (son[z][1]==y) son[z][1]=x;                
        }
    fa[x]=fa[y]; fa[y]=x; son[x][w^1]=y; update(y);
}
inline void splay(int x)
{
    int top=1,i=x,y; s[1]=i;
    while (!is_root(i)) s[++top]=i=fa[i];
    while (top) pb(s[top--]);
    while (!is_root(x))
        {
            y=fa[x];
            if (!is_root(y)) 
                if ((son[fa[y]][0]==y)^(son[y][0]==x)) rotate(x);else rotate(y);            
            rotate(x);
        }
    update(x);
}
inline void access(int x){for (int y=0; x; y=x,x=fa[x])splay(x),son[x][1]=y,update(x);}
inline void makeroot(int x){access(x),splay(x),rev1(x);}
inline void link(int x,int y){makeroot(x); fa[x]=y; access(x);}
inline void cutf(int x){access(x),splay(x);fa[son[x][0]]=0; son[x][0]=0; update(x);}
inline void cut(int x,int y){makeroot(x); cutf(y);}
inline int request(int x,int y){makeroot(x); access(y); splay(y); return maxx[y];}
//Link-Cut-Tree
struct data{int from,to,tim,id;bool f;}road[M];
struct dat{int opt,a,b,id,ans;}ask[Q];
inline void swap(int &a,int &b) {int tmp=a; a=b; b=tmp;}
inline int erfind(int u,int v)
{
    int l=1,r=m;
    while (l<=r)
        {
            int mid=(l+r)>>1;
            if (road[mid].from==u && road[mid].from==v) return mid;
            if (road[mid].from<u) l=mid+1;
            else if (road[mid].from==u && road[mid].to<v) l=mid+1;
                 else r=mid-1;
        }
    return l;
}
inline bool cmp1(data A,data B){if (A.from==B.from) return A.to<B.to; return A.from<B.from;}
inline bool cmp2(data A,data B){return A.tim<B.tim;}
inline bool cmp3(data A,data B){return A.id<B.id;}
//prework 
int main()
{
//    freopen("tube9.in","r",stdin);
//    freopen("tube.out","w",stdout);
    n=read(),m=read(),q=read();
    for (int i=1; i<=m; i++)
        {
            road[i].from=read(),road[i].to=read(),road[i].tim=read();
            if (road[i].from>road[i].to) swap(road[i].from,road[i].to);
        }
    sort(road+1,road+m+1,cmp2);
    //puts("1st OK");
    for (int i=1; i<=m; i++) road[i].id=i,val[n+i]=road[i].tim,maxx[n+i]=n+i;
    sort(road+1,road+m+1,cmp1);
    for (int i=1; i<=q; i++)
        {
            ask[i].opt=read(),ask[i].a=read(),ask[i].b=read(); int tmp;
            if (ask[i].a>ask[i].b) swap(ask[i].a,ask[i].b);
            if (ask[i].opt==2) tmp=erfind(ask[i].a,ask[i].b),road[tmp].f=1,ask[i].id=road[tmp].id;
        }
    sort(road+1,road+m+1,cmp3);
    //puts("2ed OK");
    //for (int i=1; i<=m; i++)
        //printf("%d %d %d %d !%d!\n",road[i].from,road[i].to,road[i].tim,road[i].id,road[i].f);
    init();
    for (int i=1; i<=m; i++)
        if (!road[i].f) 
            {
                if (find(road[i].from)!=find(road[i].to))
                    {
                        merge(road[i].from,road[i].to);
                        link(road[i].from,n+i); link(road[i].to,n+i);
                        if (num==n-1) break;
                    }
            }
    //printf("%d\n",num);
    //puts("3rd OK");
    for (int i=q; i>0; i--)
        {
            //printf("%d is OK: %d\n",i,request(ask[i].a,ask[i].b));
            if (ask[i].opt==1)
                ask[i].ans=val[request(ask[i].a,ask[i].b)];
            else
                {
                    int k=request(ask[i].a,ask[i].b);
                    if (road[ask[i].id].tim<val[k])
                        cut(road[k-n].from,k),cut(road[k-n].to,k),
                        link(ask[i].a,n+ask[i].id),link(ask[i].b,n+ask[i].id);
                }
            //puts("ABCDEFGHI");
        }
    //puts("4th OK");
    for (int i=1; i<=q; i++) if (ask[i].opt==1) printf("%d\n",ask[i].ans);
    return 0;
} 

 KD-Tree

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> 
#include<cmath>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f; 
}
#define inf 0x7fffffff
#define maxn 500010
int n,D,ans;
struct PointNode
{
    int l,r; int d[2],maxx[2],minn[2];
    PointNode (int x=0,int y=0) {l=r=0; d[0]=x,d[1]=y;}
    bool operator < (const PointNode & A) const {return d[D]<A.d[D];}
}p[maxn];
int dis(PointNode A,PointNode B) {return abs(A.d[1]-B.d[1])+abs(A.d[0]-B.d[0]);}
struct KDTreeNode
{
    PointNode tree[maxn<<1],Point;
    int rt,ansMax,ansMin;
    void Update(int now)
        {
            for (int i=0; i<=1; i++)
                {
                    tree[now].minn[i]=tree[now].maxx[i]=tree[now].d[i];
                    if (tree[now].l)
                        tree[now].minn[i]=min(tree[tree[now].l].minn[i],tree[now].minn[i]),
              tree[now].maxx[i]=max(tree[tree[now].l].maxx[i],tree[now].maxx[i]);
                    if (tree[now].r)
                        tree[now].minn[i]=min(tree[tree[now].r].minn[i],tree[now].minn[i]),
              tree[now].maxx[i]=max(tree[tree[now].r].maxx[i],tree[now].maxx[i]);
                }
        }    
    int BuildTree(int l,int r,int dd)
        {
            int mid=(l+r)>>1;
            D=dd; nth_element(p+l,p+mid,p+r+1);
            tree[mid]=p[mid];
            for (int i=0; i<=1; i++) tree[mid].minn[i]=tree[mid].maxx[i]=tree[mid].d[i];
            if (l<mid) tree[mid].l=BuildTree(l,mid-1,dd^1);
            if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1);
            Update(mid);
            return mid;
        }
    int disMax(int now)
        {
            if (!now) return -inf;
            int re=0;
            for (int i=0; i<=1; i++)
                re+=max(abs(tree[now].maxx[i]-Point.d[i]),abs(tree[now].minn[i]-Point.d[i]));
            return re;
        }
    int disMin(int now)
        {
            if (!now) return inf;
            int re=0;
            for (int i=0; i<=1; i++) re+=max(0,tree[now].minn[i]-Point.d[i]);
            for (int i=0; i<=1; i++) re+=max(0,Point.d[i]-tree[now].maxx[i]);
            return re;
        }
    void GetMax(int now)
        {
            if (!now) return;    
            int dl,dr,d0;
            d0=dis(tree[now],Point);
            ansMax=max(d0,ansMax);
            if (tree[now].l) dl=disMax(tree[now].l);
            if (tree[now].r) dr=disMax(tree[now].r);
            if (dl>dr)
                {
                    if (dl>ansMax) GetMax(tree[now].l);
                    if (dr>ansMax) GetMax(tree[now].r);
                }
            else
                {
                    if (dr>ansMax) GetMax(tree[now].r);
                    if (dl>ansMax) GetMax(tree[now].l);
                }
        }
    void GetMin(int now)
        {
            if (!now) return;
            int dl,dr,d0;
            d0=dis(tree[now],Point);
            if (d0) ansMin=min(ansMin,d0);
            if (tree[now].l) dl=disMin(tree[now].l);
            if (tree[now].r) dr=disMin(tree[now].r);
            if (dl<dr)
                {
                    if (dl<ansMin) GetMin(tree[now].l);
                    if (dr<ansMin) GetMin(tree[now].r);
                }
            else
                {
                    if (dr<ansMin) GetMin(tree[now].r);
                    if (dl<ansMin) GetMin(tree[now].l);
                }
        }
    int QueryMax(PointNode P) {Point=P; ansMax=-inf; GetMax(rt); return ansMax;}
    int QueryMin(PointNode P) {Point=P; ansMin=inf; GetMin(rt); return ansMin;}
}KDTree;
int main()
{
    n=read();
    for (int x,y,i=1; i<=n; i++) x=read(),y=read(),p[i].d[0]=x,p[i].d[1]=y;
    for (int i=0; i<=1; i++) p[0].maxx[i]=-inf,p[0].minn[i]=inf;
    KDTree.rt=KDTree.BuildTree(1,n,1);
    ans=inf;
    for (int i=1; i<=n; i++)
        {
            int minn=KDTree.QueryMin(p[i]),maxx=KDTree.QueryMax(p[i]);
            ans=min(ans,maxx-minn);
        }
    printf("%d\n",ans);
    return 0;
}

Splay

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
inline int read()
{
    int x=0; char ch=getchar();
    while (ch<'0' || ch>'9') {ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x;
}
#define LL long long
#define MAXN 200010 
int N,M,power[MAXN],val[MAXN];
struct EdgeNode{int next,to,d;}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int pl[MAXN],dfn,pr[MAXN],pre[MAXN],del[MAXN];
void DFS(int now,int last)
{
    pl[now]=++dfn; pre[dfn]=now; del[dfn]=1;
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=last)
            DFS(edge[i].to,now);
    pr[now]=++dfn; del[dfn]=-1;
}
namespace SplayTree
{

    int fa[MAXN],son[MAXN][2],sz,root,ln[MAXN],rn[MAXN],pos[MAXN];
    LL sum[MAXN],tag[MAXN];
    //ln记录左的数量,rn记录右的数量,tag标记 
    #define ls(x) son[x][0]
    #define rs(x) son[x][1]    
    #define INF 1000100

    inline void Update(int now)
    {
        sum[now]=sum[ls(now)]+sum[rs(now)]+(LL)val[now];
        ln[now]=ln[ls(now)]+ln[rs(now)]+(del[now]==1);
        rn[now]=rn[ls(now)]+rn[rs(now)]+(del[now]==-1);
    }
    inline void paint(int now,LL D) {if (now) val[now]+=D*del[now],sum[now]+=D*(ln[now]-rn[now]),tag[now]+=D;}
    inline void PushDown(int now)
    {
        if (!tag[now]) return;
        LL D=tag[now]; tag[now]=0;
        if (ls(now)) paint(ls(now),D);
        if (rs(now)) paint(rs(now),D);
    }     
    void print(int now)
    {
        PushDown(now);
        if (val[now]!=INF && val[now]!=-INF)
            printf("ID=%d ---%d  [%d %d]  %d   %I64d   %d   %d   %d  %I64d\n",
            now,fa[now],ls(now),rs(now),val[now],sum[now],ln[now],rn[now],del[now],tag[now]);
           if (son[now][0]) print(son[now][0]);
        if (son[now][1]) print(son[now][1]);
    }
    inline bool Right(int now) {return son[fa[now]][1]==now;}
    inline void rotate(int now)    
    {
        PushDown(fa[now]); PushDown(now);
        int f=fa[now],gf=fa[f],wh=Right(now);
        son[f][wh]=son[now][wh^1]; fa[son[f][wh]]=f;
        fa[f]=now; son[now][wh^1]=f; fa[now]=gf;
        if (gf) son[gf][son[gf][1]==f]=now;
        Update(f); Update(now);
    }
    inline void splay(int now,int tar)
    {
        for (int f; (f=fa[now])!=tar; rotate(now))
            if (fa[f]!=tar) rotate(Right(now)==Right(f)? f:now);
        if (!tar) root=now;    
    }
    inline int fmin(int x) {while (son[x][0]) x=son[x][0]; return x;}
    inline int fmax(int x) {while (son[x][1]) x=son[x][1]; return x;}
    inline void Split(int l,int r)
    {
        splay(l,0); int x=fmax(ls(root));
        splay(r,0); int y=fmin(rs(root));
        splay(x,0); splay(y,x);
    }
    inline LL Query(int pos) {Split(pl[1],pl[pos]); return sum[ls(rs(root))];}
    inline void Change(int x,int D)
    {
        Split(pl[x],pr[x]);        
        int rt=son[rs(root)][0];
        sum[rt]+=(LL)(ln[rt]-rn[rt])*D; val[rt]+=D*del[rt]; tag[rt]+=D;
        Update(rs(root)); Update(root);
    }
    inline void BuildTree(int l,int r,int last)
    {
        if (r<l) return;
        int mid=(l+r)>>1,now=mid;
        fa[now]=last; son[last][now>last]=now;
        if (l==r) 
            {sum[now]=val[now]; ln[now]=del[now]==1; rn[now]=1-ln[now]; return;}
        BuildTree(l,mid-1,now); BuildTree(mid+1,r,now);
        Update(now);
    }
    inline void Init() {BuildTree(1,(N<<1)+2,0); root=(1+(N<<1)+2)>>1;}
    inline void MakeRoot(int now,int father)
    {
        Split(pl[now],pr[now]);
        int rt=ls(rs(root));
        fa[ls(rs(root))]=0;
        son[rs(root)][0]=0;
        Update(rs(root)),Update(root);
        splay(pl[father],0); splay(fmin(rs(root)),root);
        son[rs(root)][0]=rt; fa[rt]=rs(root);
        Update(rs(root)),Update(root);
    }
}
using namespace SplayTree;
int main()
{
    N=read();
    for (int i=2; i<=N; i++) InsertEdge(i,read());
    dfn=1; DFS(1,0);
    for (int i=1; i<=N; i++) power[i]=read();
//    for (int i=1; i<=N; i++) printf("id=%d [%d , %d]\n",pre[i],pl[pre[i]],pr[pre[i]]);
    for (int i=1; i<=N; i++) val[pl[i]]+=power[i],val[pr[i]]-=power[i];
//    for (int i=1; i<=dfn; i++) printf("%d ",val[i]); puts("");
    M=read(); 
    SplayTree::Init();
    while (M--)
        {
//            print(root);
            char opt[5]; scanf("%s",opt); int x,y;
            if (opt[0]=='Q') x=read(),printf("%I64d\n",SplayTree::Query(x));
            if (opt[0]=='C') x=read(),y=read(),SplayTree::MakeRoot(x,y);
            if (opt[0]=='F') x=read(),y=read(),SplayTree::Change(x,y); 
        }
    return 0;
}

主席树  不带修&带修

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define maxn 100100
#define maxm 500100
int n,m,q; int hh[maxn],ls[maxn]; int steck[maxn<<2],top;
struct data{
int from,to,hard;
bool operator < (const data& A) const
    {return hard<A.hard;}
}road[maxm];
struct dat{int next,to;}edge[maxn<<1];int head[maxn<<1],cnt;
void add(int u,int v){cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
int fa[maxn<<1],va[maxn<<1];
void init(){for (int i=1; i<=n*2; i++) fa[i]=i;}
int find(int x) {if (x==fa[x]) return x; return fa[x]=find(fa[x]);}
void Kruskal()
{
    init(); int zz=n;
    sort(road+1,road+m+1);
    for (int i=1; i<=m; i++)
        {
            
            int u=road[i].from,v=road[i].to,w=road[i].hard;
            int fa1=find(u),fa2=find(v);
            if (fa1!=fa2)
                {
                    zz++; fa[fa1]=fa[fa2]=zz; va[zz]=w;
                    add(zz,fa2);add(zz,fa1);
                    if (zz==2*n-1) break;
                }
        }
}
bool visit[maxn<<1];int father[maxn<<1][20],maxx[maxn<<1][20],deep[maxn<<1];
void dfs(int x)
{
    visit[x]=1; steck[++top]=x;
    for (int i=1; i<20; i++)
        if (deep[x]>=(1<<i))
            father[x][i]=father[father[x][i-1]][i-1],
            maxx[x][i]=max(maxx[x][i-1],maxx[father[x][i-1]][i-1]);
        else break;
    for (int i=head[x]; i; i=edge[i].next)
        {
            deep[edge[i].to]=deep[x]+1;
            maxx[edge[i].to][0]=va[x];
            father[edge[i].to][0]=x;
            dfs(edge[i].to);
        }
    if (x>n) steck[++top]=x;
}
int sum[maxn*20],ll[maxn*20],rr[maxn*20],root[maxn<<2],sz;
void insert(int l,int r,int &now,int fat,int val)
{
    now=++sz; sum[now]=sum[fat]+1;
    if (l==r) return;
    ll[now]=ll[fat],rr[now]=rr[fat];
    int mid=(l+r)>>1;
    if (val<=mid) insert(l,mid,ll[now],ll[fat],val);
    else insert(mid+1,r,rr[now],rr[fat],val);
}
int query(int l,int r,int L,int R,int kth)
{
    if (l==r) return l;
    int mid=(l+r)>>1;
    if (sum[ll[R]]-sum[ll[L]]>=kth) return query(l,mid,ll[L],ll[R],kth);
    else return query(mid+1,r,rr[L],rr[R],kth-sum[ll[R]]+sum[ll[L]]);
}
int st[maxn<<2],ed[maxn<<2];
void prework()
{
    for (int i=1; i<=n; i++)
        if (!visit[i]) dfs(find(i));
    for (int  i=1; i<=top; i++)
        {
            int tmp=steck[i];
            if (tmp<=n) insert(1,n,root[i],root[i-1],hh[tmp]);
            else 
                {
                    root[i]=root[i-1];
                    if (!st[tmp]) st[tmp]=i; else ed[tmp]=i;
                }
        }
}
int search(int x,int val)
{
    for(int i=19;i>=0;i--)
        if(deep[x]>=(1<<i) && maxx[x][i]<=val) x=father[x][i];
    return x;
}
int main()
{
    n=read(),m=read(),q=read();
    for (int i=1; i<=n; i++) hh[i]=read(),ls[i]=hh[i];
    sort(ls+1,ls+n+1); 
    for (int i=1; i<=n; i++)
        hh[i]=lower_bound(ls+1,ls+n+1,hh[i])-ls;
    for (int i=1; i<=m; i++)
        road[i].from=read(),road[i].to=read(),road[i].hard=read();
    Kruskal();
    prework();
    int lastans=-1,ans;
    for (int i=1; i<=q; i++)
        {
            int v=read(),x=read(),k=read();
            if (lastans!=-1) v^=lastans,x^=lastans,k^=lastans;
            int tmp=search(v,x);
               int a=root[st[tmp]],b=root[ed[tmp]];
            if (sum[b]-sum[a]<k) ans=-1;
            else ans=ls[query(1,n,a,b,sum[b]-sum[a]-k+1)];
            printf("%d\n",ans); lastans=ans;
        }
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 100010
#define vec vector<int>
int N,Q,ls[MAXN<<1],tp,val[MAXN];
struct QNode{int x,y,z,opt;}q[MAXN];
struct EdgeNode{int next,to;}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int pl[MAXN],dfn,pr[MAXN],deep[MAXN],father[17][MAXN];
inline void DFS(int now,int last)
{
    pl[now]=++dfn;
    for (int i=1; i<=16; i++)
        if (deep[now]>=(1<<i)) father[i][now]=father[i-1][father[i-1][now]];
            else break;
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=last)
            father[0][edge[i].to]=now,deep[edge[i].to]=deep[now]+1,
            DFS(edge[i].to,now);
    pr[now]=dfn;
}
inline int LCA(int x,int y)
{
    if (deep[x]<deep[y]) swap(x,y);
    int dd=deep[x]-deep[y];
    for (int i=0; i<=16; i++)
        if (dd&(1<<i)) x=father[i][x];
    for (int i=16; i>=0; i--)
        if (father[i][x]!=father[i][y])
            x=father[i][x],y=father[i][y];
    return x==y? x:father[0][x];
}
namespace PrTree
{
    int lson[MAXN*80],rson[MAXN*80],sum[MAXN*80],sz,root[MAXN];
    vec add,sub;
    inline void Insert(int l,int r,int &now,int fa,int pos,int val)
    {
        now=++sz; sum[now]=sum[fa]+val;
        if (l==r) {return;}
        lson[now]=lson[fa],rson[now]=rson[fa];
        int mid=(l+r)>>1;
        if (pos<=mid) Insert(l,mid,lson[now],lson[fa],pos,val);
            else Insert(mid+1,r,rson[now],rson[fa],pos,val);
    }
    inline int Query(int l,int r,int kth)
    {
        if (l==r) return l;
        int mid=(l+r)>>1,sn=0,sr=0;
        for (int i=0; i<add.size(); i++) sr+=sum[rson[add[i]]],sn+=sum[add[i]];
        for (int i=0; i<sub.size(); i++) sr-=sum[rson[sub[i]]],sn-=sum[sub[i]];
        if (sn<kth) return -1;
        if (kth>sr)
            {
                for (int i=0; i<add.size(); i++) add[i]=lson[add[i]];
                for (int i=0; i<sub.size(); i++) sub[i]=lson[sub[i]];
                Query(l,mid,kth-sr);
            }
        else
            {
                for (int i=0; i<add.size(); i++) add[i]=rson[add[i]];
                for (int i=0; i<sub.size(); i++) sub[i]=rson[sub[i]];
                Query(mid+1,r,kth);
            }
    }
    inline void BuildTree(int now,int last)
    {
        Insert(1,tp,root[now],root[last],val[now],1);
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last)
                BuildTree(edge[i].to,now);
    }
}using namespace PrTree;
namespace BIT
{
    int tree[MAXN];
    inline int lowbit(int x) {return x&-x;}
    inline void Modify(int x,int pos,int D)
    {
        for (int i=x; i<=dfn; i+=lowbit(i))
            Insert(1,tp,tree[i],tree[i],pos,D);
    }
    inline int Add(int x)
    {
        add.push_back(root[x]);
        for (int i=pl[x]; i; i-=lowbit(i))
            add.push_back(tree[i]);
    }
    inline int Sub(int x)
    {
        sub.push_back(root[x]);
        for (int i=pl[x]; i; i-=lowbit(i))
            sub.push_back(tree[i]);
    }
    inline void Clear() {add.clear(); sub.clear();}
}using namespace BIT;
int main()
{
    N=read(); Q=read();
    for (int i=1; i<=N; i++) val[i]=read(),ls[++tp]=val[i];
    for (int i=1,x,y; i<=N-1; i++) x=read(),y=read(),InsertEdge(x,y);
    DFS(1,0);
    for (int i=1; i<=Q; i++)
        {
            q[i].opt=read(),q[i].x=read(),q[i].y=read();
            if (q[i].opt) q[i].z=LCA(q[i].x,q[i].y); else ls[++tp]=q[i].y;
        }
    sort(ls+1,ls+tp+1); tp=unique(ls+1,ls+tp+1)-ls-1;
    for (int i=1; i<=N; i++) val[i]=lower_bound(ls+1,ls+tp+1,val[i])-ls;
    for (int i=1; i<=Q; i++) if (!q[i].opt) q[i].y=lower_bound(ls+1,ls+tp+1,q[i].y)-ls;
    BuildTree(1,0);
    for (int i=1; i<=Q; i++)
        {
            int opt=q[i].opt,x=q[i].x,y=q[i].y,z=q[i].z;
            if (!opt)
                Modify(pl[x],val[x],-1),Modify(pr[x]+1,val[x],1),Modify(pl[x],y,1),Modify(pr[x]+1,y,-1),val[x]=y;
            else
                {
                    Clear();
                    Add(x); Add(y); Sub(z); Sub(father[0][z]);
                    int ans=Query(1,tp,opt);
                    if (ans==-1) puts("invalid request!"); else printf("%d\n",ls[ans]);
                }
        }
    return 0;
}

块状链表

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<ctime>
using namespace std;
#define LL long long
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 100010
int Bsize,N,Q,a[MAXN];
namespace BlockLists
{
    #define BN 5010
    struct BLNode{int next,data[1010],tag,tmp[1010],size,maxx,minn,del; LL sum; bool rev;}B[BN];
    int start,ID;
    queue<int>trash;
    inline int New() {if (trash.empty()) return ++ID; int tmp=trash.front(); trash.pop(); return tmp;}
    inline void Del(int x) {trash.push(x); B[x].next=-1; B[x].size=B[x].maxx=B[x].minn=B[x].sum=B[x].tag=B[x].rev=B[x].del=0;}
    inline int GetP(int rk) {int p; for (p=start; ~B[p].next && rk>B[p].size; p=B[p].next) rk-=B[p].size; return p;}
    inline int GetK(int rk) {int p; for (p=start; ~B[p].next && rk>B[p].size; p=B[p].next) rk-=B[p].size; return rk;}
    inline void PushDown(int x)
    {
        int sz=B[x].size; 
        if (B[x].del) {int del=B[x].del; B[x].del=0; for (int i=1; i<=sz; i++) B[x].data[i]=del; B[x].sum=sz*del;}
        if (B[x].rev) {reverse(B[x].data+1,B[x].data+sz+1); B[x].rev^=1;}
        if (B[x].tag) {int tag=B[x].tag; B[x].tag=0; for (int i=1; i<=sz; i++) B[x].data[i]+=tag; B[x].sum+=(LL)sz*tag;}
    }
    inline void Update(int x)
    {
        int sz=B[x].size; B[x].sum=0;
        for (int i=1; i<=sz; i++) B[x].sum+=B[x].data[i],B[x].tmp[i]=B[x].data[i];
        sort(B[x].tmp+1,B[x].tmp+sz+1);
        B[x].minn=B[x].tmp[1],B[x].maxx=B[x].tmp[B[x].size];
    }
    inline void Split(int pos,int rk)
    {
        PushDown(pos);
        int id=New(); for (int i=rk; i<=B[pos].size; i++) B[id].data[++B[id].size]=B[pos].data[i]; B[id].next=B[pos].next;
        B[pos].next=id; B[pos].size=max(rk-1,0);
        Update(id); Update(pos);
    }
    inline void Merge(int pos)
    {
        for ( ; ~pos; pos=B[pos].next)
            for (int suf=B[pos].next; ~suf && B[pos].size+B[suf].size<=Bsize; suf=B[suf].next)
                {
                    PushDown(pos),PushDown(suf);
                       for (int k=1; k<=B[suf].size; k++) B[pos].data[++B[pos].size]=B[suf].data[k];
                    B[pos].next=B[suf].next,Del(suf),Update(pos);
                   }
    }
    inline void Insert(int s,int x)
    {
        int now=GetP(s+1),pos=GetK(s+1); Split(now,pos);
        B[now].data[++B[now].size]=x; Update(now); Merge(now);
    }
    inline void Delete(int s)
    {
        int now=GetP(s),pos=GetK(s); PushDown(now);
        for (int i=pos+1; i<=B[now].size; i++) B[now].data[i-1]=B[now].data[i]; B[now].size--;
        Update(now),Merge(now);
    }
    inline void Prework(int l,int r,int &x,int &y)
    {
        int now1=GetP(l),pos1=GetK(l);  Split(now1,pos1);
        int now2=GetP(r+1),pos2=GetK(r+1);  Split(now2,pos2);
        x=now1,y=GetP(r);
    }
    int st[MAXN];
    inline void Rever(int l,int r)
    {
        int x,y,top=0; Prework(l,r,x,y);
        for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) st[++top]=i,B[i].rev^=1;
        B[st[1]].next=B[y].next;
        for (int i=top; i>1; i--) B[st[i]].next=st[i-1];
        B[x].next=y; Merge(x);
    }
    inline void Move(int l,int r,int k)
    {
        int x,y,z,tmp; Prework(l,r-k,x,z); Prework(r-k+1,r,z,y);
        tmp=B[x].next; B[x].next=B[z].next,B[z].next=B[y].next,B[y].next=tmp;
        Merge(x);
    }
    inline void Add(int l,int r,int D)
    {
        int x,y; Prework(l,r,x,y);
        for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) B[i].sum+=(LL)B[i].size*D,B[i].tag+=D;
        Merge(x);
    }
    inline void Modify(int l,int r,int val)
    {
        int x,y; Prework(l,r,x,y);
        for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) B[i].tag=0,B[i].del=val,B[i].sum=(LL)B[i].size*val;
        Merge(x);
    }
    inline LL GetSum(int l,int r)
    {
        int x,y; LL re=0; Prework(l,r,x,y);
        for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) re+=B[i].sum;
        Merge(x); return re;
    }
    #define INF 0x7fffffff
    inline int GetRange(int l,int r)
    {
        int x,y,maxx=-INF,minn=INF; Prework(l,r,x,y);
        for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) 
            if (B[i].del) maxx=max(maxx,B[i].del+B[i].tag),minn=min(minn,B[i].del+B[i].tag);
                else maxx=max(maxx,B[i].maxx+B[i].tag),minn=min(minn,B[i].minn+B[i].tag);
        Merge(x); return maxx-minn;
    }
    inline int GetClose(int l,int r,int val)
    {
        int x,y,re=INF; Prework(l,r,x,y);
        for (int t,i=B[x].next; ~i && i!=B[y].next; i=B[i].next)
            if (B[i].del) re=min(re,abs(val-(B[i].del+B[i].tag)));
                else
                    {
                           t=lower_bound(B[i].tmp+1,B[i].tmp+B[i].size+1,val-B[i].tag)-B[i].tmp;
                           if (t!=B[i].size+1) re=min(re,abs(B[i].tmp[t]+B[i].tag-val));
                        if (t!=1) re=min(re,abs(val-(B[i].tmp[t-1]+B[i].tag))); 
                    }
        Merge(x); return re;
    }
    inline int GetKth(int l,int r,int k)
    {
        int x,y,t=-INF; Prework(l,r,x,y);
        for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) t=max(t,B[i].del? B[i].del+B[i].tag:B[i].maxx+B[i].tag);
        int L=0,R=t;
        while (L<R)
            {
                int mid=((L+R)>>1)+1,re=1;
                for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) 
                    if (B[i].del) if (B[i].del+B[i].tag<mid) re+=B[i].size; else;
                        else t=upper_bound(B[i].tmp+1,B[i].tmp+B[i].size+1,mid-1-B[i].tag)-B[i].tmp,re+=max(0,t-1);
                if (k>=re) L=mid; else R=mid-1;
            }
        Merge(x); return L;
    }
    inline int GetSmall(int l,int r,int val)
    {
        int x,y,re=0; Prework(l,r,x,y);
        for (int t,i=B[x].next; ~i && i!=B[y].next; i=B[i].next) 
            if (B[i].del) if (B[i].del+B[i].tag<val) re+=B[i].size; else;
                else t=upper_bound(B[i].tmp+1,B[i].tmp+B[i].size+1,val-B[i].tag-1)-B[i].tmp,re+=t-1;
        Merge(x); return re;
    }
    inline void Init() {start=0; ID=0; B[0].next=-1; B[0].size=0;}
}
using namespace BlockLists;
int main()
{
//    freopen("data.in","r",stdin);
//    freopen("ORZJRY.out","w",stdout);
    int N=read();
    Init();
    for (int x,i=1; i<=N; i++) x=read(),Insert(i-1,x);
    Bsize=sqrt(N+(rand()%((int)sqrt(N))) );
    Q=read();
    while (Q--)
        {
//            puts("=============================================");
            int opt=read(); int x,y,k;
//            printf("%d   :",opt);
            switch (opt)
                {
                    case 1: x=read(),k=read(),Insert(x,k); break;
                    case 2: x=read(); Delete(x); break;
                    case 3: x=read(),y=read(); Rever(x,y); break;
                    case 4: x=read(),y=read(),k=read(); Move(x,y,k); break;
                    case 5: x=read(),y=read(),k=read(); Add(x,y,k); break;
                    case 6: x=read(),y=read(),k=read(); Modify(x,y,k); break;
                    case 7: x=read(),y=read(); printf("%lld\n",GetSum(x,y)); break;
                    case 8: x=read(),y=read(); printf("%d\n",GetRange(x,y)); break;
                    case 9: x=read(),y=read(),k=read(); printf("%d\n",GetClose(x,y,k)); break;
                    case 10: x=read(),y=read(),k=read(); printf("%d\n",GetKth(x,y,k)); break;
                    case 11: x=read(),y=read(),k=read(); printf("%d\n",GetSmall(x,y,k)); break;
                }
//            puts("");
        }
    return 0;
}

图论相关

网络流  最大流&费用流&zkw费用流&分治最小割

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f; 
}
#define MAXN 1010
#define MAXM 1001010 
int L,W,N;
struct PointNode{int x,y;}P[MAXN];
struct EdgeNode{int next,to,cap;}edge[MAXM];
int head[MAXN],cnt=1;
void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,0);}
queue<int>q;
int cur[MAXN],S,T,h[MAXN];
#define INF 0x7fffffff
bool bfs()
{
    queue<int>q;
    for (int i=S; i<=T; i++) h[i]=-1;
    h[S]=1; q.push(S);
    while (!q.empty())
        {
            int now=q.front(); q.pop();
            for (int i=head[now]; i; i=edge[i].next)
                if (h[edge[i].to]==-1 && edge[i].cap)
                    h[edge[i].to]=h[now]+1,q.push(edge[i].to);
        }
    return h[T]!=-1;        
}
int dfs(int loc,int low)
{
    if (loc==T) return low;
    int used=0,w;
    for (int i=cur[loc]; i; i=edge[i].next)
        if (edge[i].cap && h[edge[i].to]==h[loc]+1)
            {
                w=dfs(edge[i].to,min(edge[i].cap,low-used));
                edge[i].cap-=w; edge[i^1].cap+=w; used+=w;
                if (used==low) return low;
                if (edge[i].to) cur[loc]=i;
            }
    if (!used) h[loc]=-1;
    return used;
}
int Dinic()
{
    int tmp=0;
    while (bfs())
        {
            for (int i=S; i<=T; i++) cur[i]=head[i];
            tmp+=dfs(S,INF);
        }
    return tmp;
}
int Dis(PointNode a,PointNode b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int main()
{
    L=read(),W=read(),N=read();
    for (int x,y,i=1; i<=N; i++) P[i].x=read(),P[i].y=read();
    S=0,T=2*N+1;
    for (int i=1; i<=N; i++)
        for (int j=1; j<=N; j++)
            if (Dis(P[i],P[j])<=200 && i!=j) InsertEdge(i+N,j,INF);
    for (int i=1; i<=N; i++)
        {
            if (P[i].y<=100) InsertEdge(S,i,INF);
            if (abs(W-P[i].y)<=100) InsertEdge(i+N,T,INF);
            InsertEdge(i,i+N,1);
        }
    printf("%d\n",Dinic());
    return 0;
}
#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#include<cmath> 
#include<queue> 
using namespace std; 
int read() 
{ 
    int x=0,f=1; char ch=getchar(); 
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 
    return x*f; 
} 
#define maxp 1000 
#define maxn 100010 
#define maxm 1000010 
int n,m,S,T,ans,tot;int p[maxp],tt[maxp][maxp]; 
struct data{int from,next,to,cap,cost;}edge[maxm<<2]; 
int head[maxn],from[maxn],cnt=1; 
void add(int u,int v,int w,int c) 
{cnt++;edge[cnt].from=u;edge[cnt].to=v; 
edge[cnt].next=head[u];head[u]=cnt; 
edge[cnt].cost=c;edge[cnt].cap=w;} 
void insert(int u,int v,int w,int c){add(u,v,w,c);add(v,u,0,-c);} 
#define inf 0x7fffffff 
bool visit[maxn];int dis[maxn]; 
bool spfa() 
{ 
    queue<int>q; 
    for (int i=S; i<=T; i++) dis[i]=inf; 
    q.push(S); visit[S]=1; dis[S]=0; 
    while (!q.empty()) 
        { 
            int now=q.front(); q.pop(); 
            for (int i=head[now]; i; i=edge[i].next) 
                if (edge[i].cap && dis[now]+edge[i].cost<dis[edge[i].to]) 
                    { 
                        dis[edge[i].to]=dis[now]+edge[i].cost; from[edge[i].to]=i; 
                        if (!visit[edge[i].to]) 
                            q.push(edge[i].to),visit[edge[i].to]=1; 
                    } 
            visit[now]=0; 
        } 
    return dis[T]!=inf; 
} 
void MinCostMaxFlow() 
{ 
    int flow=inf,a,b,x; 
    for (int i=from[T]; i; i=from[edge[i].from]) 
        { 
            flow=min(flow,edge[i].cap); 
            if (!edge[i].from) x=edge[i].to,a=(x-1)/tot+1,b=x%tot+1; 
        } 
    for (int i=from[T]; i; i=from[edge[i].from]) 
        edge[i].cap-=flow,edge[i^1].cap+=flow,ans+=edge[i].cost*flow;
    for (int i=1; i<=n; i++) 
        insert((a-1)*tot+b,m*tot+i,1,b*tt[i][a]); 
} 
void make() 
{ 
    S=0,T=100001; 
    for (int i=1; i<=tot*m; i++) 
        insert(S,i,1,0); 
    for (int i=1; i<=n; i++) 
        insert(m*tot+i,T,p[i],0); 
    for (int i=1; i<=m; i++) 
        for (int j=1; j<=n; j++) 
            insert((i-1)*tot+1,m*tot+j,1,tt[j][i]); 
} 
int main() 
{ 
    n=read(),m=read(); 
    for (int i=1; i<=n; i++) p[i]=read(),tot+=p[i]; 
    for (int i=1; i<=n; i++) 
        for (int j=1; j<=m; j++) 
            tt[i][j]=read(); 
    make(); 
    while (spfa()) MinCostMaxFlow();
    printf("%d\n",ans); 
    return 0; 
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 11000
#define MAXM 500010
#define INF 0x7fffffff
int N,mp[110][110],id[110][110],e[10100][110];
struct EdgeNode{int next,to,from,cap,cost;}edge[MAXM<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v,int w,int c) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].from=u; edge[cnt].cost=c; edge[cnt].cap=w;}
inline void InsertEdge(int u,int v,int w,int c) {AddEdge(u,v,w,c); AddEdge(v,u,0,-c);}
int mark[MAXM],dis[MAXM],Flow,Cost,S,T;
inline bool SPFA()
{
    for (int i=S; i<=T; i++) dis[i]=INF,mark[i]=0;
    queue<int>q;
    q.push(S); dis[S]=0; mark[S]=1;
    while (!q.empty())
        {
            int now=q.front(); q.pop(); mark[now]=0;
            for (int i=head[now]; i; i=edge[i].next)
                if (edge[i].cap && dis[edge[i].to]>dis[now]+edge[i].cost)
                    {
                        dis[edge[i].to]=dis[now]+edge[i].cost;
                        if (!mark[edge[i].to]) q.push(edge[i].to),mark[edge[i].to]=1;
                    }
        }
    return dis[T]!=INF;
}
inline int DFS(int loc,int low)
{
    mark[loc]=1;
    if (loc==T) return low;
    int used=0,w;
    for (int i=head[loc]; i; i=edge[i].next)
        if (edge[i].cap && !mark[edge[i].to] && dis[edge[i].to]==dis[loc]+edge[i].cost)
            {
                w=DFS(edge[i].to,min(edge[i].cap,low-used));
                edge[i].cap-=w; edge[i^1].cap+=w; used+=w; Cost+=w*edge[i].cost;
                if (low==used) return used;
            }
    return used;
}
inline int ZKW()
{
    int re=0;
    while (SPFA())
        {
            mark[T]=1;
            while (mark[T])
                {
                    for (int i=S; i<=T; i++) mark[i]=0;
                    re+=DFS(S,INF);
                }
        }
    return re;
}
int main()
{
    N=read();
    for (int i=1; i<=N; i++)
        for (int j=1; j<=N; j++) mp[i][j]=read();
    int ID=N;
    for (int i=1; i<=N; i++)
        for (int j=1; j<=N; j++) id[i][j]=++ID;
    S=0; T=ID+1;
    for (int i=1; i<=N; i++)
        for (int j=i+1; j<=N; j++)
            if (i!=j)
                {
                    InsertEdge(S,id[i][j],1,0);
                    switch (mp[i][j])
                        {
                            case 1: InsertEdge(id[i][j],i,1,0); break;
                            case 0: InsertEdge(id[i][j],j,1,0); break;
                            case 2: InsertEdge(id[i][j],i,1,0); e[id[i][j]][i]=cnt-1;
                                    InsertEdge(id[i][j],j,1,0); e[id[i][j]][j]=cnt-1; break;
                        }
                }
    for (int i=1; i<=N; i++)
        for (int j=1; j<=N; j++) InsertEdge(i,T,1,j-1);
    ZKW();
    printf("%d\n",N*(N-2)*(N-1)/6-Cost);
    for (int i=1; i<=N; i++)
        for (int j=i+1; j<=N; j++)
            if (mp[i][j]==2)
                {
                    mp[i][j]=edge[e[id[i][j]][i]].cap==0;
                    mp[j][i]=mp[i][j]^1;
                }
    for (int i=1; i<=N; i++,puts(""))
        for (int j=1; j<=N; j++) printf("%d ",mp[i][j]);
    return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
#define maxn 200
#define maxm 100010
int n,m,q,t,ans[maxn][maxn],id[maxn],tmp[maxn];
struct Edgenode{int next,to,cap;}edge[maxm];
int head[maxn],cnt=1;
void add(int u,int v,int w)
{cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w;}
void insert(int u,int v,int w) {add(u,v,w); add(v,u,w);}
int dis[maxn],que[maxn<<1],cur[maxn],S,T;
bool bfs()
{
    memset(dis,-1,sizeof(dis));
    que[0]=S; dis[S]=0; int he=0,ta=1;
    while (he<ta)
        {
            int now=que[he++];
            for (int i=head[now]; i; i=edge[i].next)
                if (edge[i].cap && dis[edge[i].to]==-1)
                    dis[edge[i].to]=dis[now]+1,que[ta++]=edge[i].to;
        }
    return dis[T]!=-1;
}
int dfs(int loc,int low)
{
    if (loc==T) return low;
    int w,used=0;
    for (int i=cur[loc]; i; i=edge[i].next)
        if (edge[i].cap && dis[edge[i].to]==dis[loc]+1)
            {
                w=dfs(edge[i].to,min(low-used,edge[i].cap));
                edge[i].cap-=w; edge[i^1].cap+=w;
                used+=w; if (edge[i].cap) cur[loc]=i;
                if (used==low) return low;
            }
    if (!used) dis[loc]=-1;
    return used;
}
#define inf 0x7fffffff
int dinic()
{
    int tmp=0;
    while (bfs())
        {
            for (int i=1; i<=n; i++) cur[i]=head[i];
            tmp+=dfs(S,inf);
        }
    return tmp;
}
void init()
{
    cnt=1;
    memset(ans,127,sizeof(ans));
    memset(head,0,sizeof(head));
}
bool visit[maxn];
void DFS(int x)
{
    visit[x]=1;
    for (int i=head[x]; i; i=edge[i].next)
        if (edge[i].cap && !visit[edge[i].to])
            DFS(edge[i].to);
}
void work(int L,int R)
{
    if (L==R) return;
    for (int i=2; i<=cnt; i+=2) 
        edge[i].cap=edge[i^1].cap=(edge[i].cap+edge[i^1].cap)>>1;
    S=id[L],T=id[R];
    int maxflow=dinic();
    memset(visit,0,sizeof(visit)); DFS(S);
    for (int i=1; i<=n; i++) if (visit[i])
        for (int j=1; j<=n; j++) if (!visit[j])
            ans[i][j]=ans[j][i]=min(ans[i][j],maxflow);
    int l=L,r=R;
    for (int i=L; i<=R; i++)
        if (visit[id[i]])
            tmp[l++]=id[i];
        else tmp[r--]=id[i];
    for (int i=L; i<=R; i++) id[i]=tmp[i];
    work(L,l-1); work(r+1,R);
}        
int main()
{
//    freopen("mincuto.in","r",stdin);
//    freopen("mincuto.out","w",stdout);
    t=read();
    while (t--)
        {
            init();
            n=read(),m=read();
            for (int i=1; i<=n; i++) id[i]=i;
            for (int u,v,w,i=1; i<=m; i++)
                u=read(),v=read(),w=read(),insert(u,v,w);
            work(1,n);
            q=read();
            for (int c,i=1; i<=q; i++)
                {
                    c=read(); int an=0;
                    for (int j=1; j<=n; j++)
                        for (int k=j+1; k<=n; k++)
                            if (ans[j][k]<=c) an++;
                    printf("%d\n",an); 
                }
            puts("");
        }
    return 0;
}

拓扑排序

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define maxn 1000
#define maxm 1000010
int n,m,total,score[maxn];
struct EdgeNode{int next,to,cap;}edge[maxm];
int head[maxn],cnt=1;
void addedge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
void insertedge(int u,int v,int w) {addedge(u,v,w); addedge(v,u,0);}

struct RoadNode{int next,to;}road[maxm>>1];
int last[maxn],tot;
void addroad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;}
void insertroad(int u,int v) {addroad(u,v);}
bool visit[maxn]; int du[maxn],s,t;
void Paint(int now)
{
    visit[now]=1;
    for (int i=last[now]; i; i=road[i].next)
        if (!visit[road[i].to]) Paint(road[i].to);
}
void TopoSort()
{
    s=1,t=n*m;
    stack<int>st;
    for (int i=s; i<=t; i++) if (!du[i]) st.push(i); else visit[i]=1;
    while (!st.empty())
        {
            int now=st.top(); st.pop(); visit[now]=0;
            for (int i=last[now]; i; i=road[i].next)
                {
                    du[road[i].to]--;
                    if (!du[road[i].to]) st.push(road[i].to);
                }
            //printf("%d\n",now);
        }
    for (int i=s; i<=t; i++) if (visit[i]) Paint(i);
}
int dis[maxn],cur[maxn],S,T;
#define inf 0x7fffffff
bool bfs()
{
    queue<int>q;
    for (int i=S; i<=T; i++) dis[i]=-1;
    q.push(S); dis[S]=0;
    while (!q.empty())
        {
            int now=q.front(); q.pop();
            for (int i=head[now]; i; i=edge[i].next)
                if (edge[i].cap && dis[edge[i].to]==-1)
                    dis[edge[i].to]=dis[now]+1,q.push(edge[i].to);
        }
    return dis[T]!=-1;
}
int dfs(int loc,int low)
{
    if (loc==T) return low;
    int w,used=0;
    for (int i=cur[loc]; i; i=edge[i].next)
        if (edge[i].cap && dis[edge[i].to]==dis[loc]+1)
            {
                w=dfs(edge[i].to,min(low-used,edge[i].cap));
                edge[i].cap-=w; edge[i^1].cap+=w; used+=w;
                if (used==low) return low; if (edge[i].cap) cur[loc]=i;
            }
    if (!used) dis[loc]=-1;
    return used;
}
int dinic()
{
    int tmp=0;
    while (bfs())
        {
            for (int i=S; i<=T; i++) cur[i]=head[i];
            tmp+=dfs(S,inf);
        }
    return tmp;
}
void Build()
{
    S=0,T=n*m+1;
    for (int i=1; i<=n*m; i++)
        if (!visit[i])
            {
                if (score[i]>0) insertedge(i,T,score[i]); else insertedge(S,i,-score[i]);
                for (int j=last[i]; j; j=road[j].next)
                    if (!visit[road[j].to]) insertedge(i,road[j].to,inf);
                total+=score[i]>0?score[i]:0;
            }
}
int locate(int x,int y) {return (x-1)*m+y;}
int main()
{
    n=read(),m=read();
    for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++)
            {
                int now=locate(i,j),num;
                score[now]=read(); num=read();
                for (int x,y,k=1; k<=num; k++)
                    x=read()+1,y=read()+1,insertroad(now,locate(x,y)),du[locate(x,y)]++;
                if (j>1) insertroad(now,locate(i,j-1)),du[locate(i,j-1)]++;
            }
    TopoSort();
    Build();
    int maxflow=dinic();// printf("%d %d\n",total,maxflow);
    printf("%d\n",total-maxflow);
    return 0;
}

Tarjan  强连通分量&双连通分量+割点

//BZOJ-1179
#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#include<queue> 
using namespace std; 
#define maxn 500010 
int read() 
{ 
    int x=0,f=1; char ch=getchar(); 
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 
    return x*f; 
} 
int n,m,uu,S,P,ans,val[maxn]; 
  
struct Edgenode{int to,next,val;}edge[maxn<<1]; 
int head[maxn<<1],cnt=1; 
void add(int u,int v) 
{cnt++;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;} 
struct Roadnode{int to,next;}road[maxn]; 
int last[maxn],cn=1; 
void insert(int u,int v) 
{cn++;road[cn].to=v;road[cn].next=last[u];last[u]=cn;} 
int dfn[maxn],low[maxn],qcnt,stack[maxn],top,num[maxn],belong[maxn],tot,valu[maxn]; 
bool visit[maxn]; 
  
void Tarjan(int x) 
{ 
    dfn[x]=low[x]=++tot; 
    visit[x]=1; stack[++top]=x; 
    for (int i=head[x]; i; i=edge[i].next) 
        { 
            if (!dfn[edge[i].to]) 
                { 
                    Tarjan(edge[i].to); 
                    if (low[edge[i].to]<low[x]) low[x]=low[edge[i].to]; 
                } 
            else 
                if(visit[edge[i].to] && dfn[edge[i].to]<low[x]) 
                    low[x]=dfn[edge[i].to]; 
        } 
    if (dfn[x]==low[x]) 
        { 
            qcnt++; 
            while (x!=uu) 
                uu=stack[top--],num[qcnt]++,visit[uu]=0,belong[uu]=qcnt,valu[qcnt]+=val[uu];  
        } 
} 
void rebuild() 
{ 
    for (int i=1; i<=n; i++) 
        for (int j=head[i]; j; j=edge[j].next) 
            if (belong[i]!=belong[edge[j].to]) 
                insert(belong[i],belong[edge[j].to]); 
} 
#define inf 0x7fffffff 
int dis[maxn]; 
void spfa() 
{ 
    queue<int>que; memset(visit,0,sizeof(visit)); 
//  for (int i=1; i<=qcnt; i++) dis[i]=-inf; 
    visit[S]=1; dis[S]=valu[S]; que.push(S); 
    while (!que.empty()) 
        { 
            int now=que.front(); que.pop(); visit[now]=0; 
            for (int i=last[now]; i; i=road[i].next) 
                if (dis[road[i].to]<dis[now]+valu[road[i].to]) 
                    { 
                        dis[road[i].to]=dis[now]+valu[road[i].to]; 
                        if (!visit[road[i].to]) 
                            visit[road[i].to]=1,que.push(road[i].to); 
                    } 
        } 
} 
bool bar[maxn]; 
int main() 
{ 
    n=read(),m=read(); 
    for (int u,v,i=1; i<=m; i++) u=read(),v=read(),add(u,v); 
    for (int i=1; i<=n; i++) val[i]=read(); 
    for (int i=1; i<=n; i++) if (!dfn[i]) Tarjan(i); 
    S=read(); S=belong[S]; P=read(); 
    for (int x,i=1; i<=P; i++) x=read(),bar[x]=1; 
    rebuild(); spfa(); 
//  for (int i=1; i<=n; i++) 
//      printf("%d\n",dis[belong[i]]); 
    for (int i=1; i<=n; i++) 
        if (bar[i]) ans=max(ans,dis[belong[i]]); 
    printf("%d\n",ans); 
    return 0; 
}
//UOJ67
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define LL long long
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 100010
int N,M,tot;
LL sum;
struct EdgeNode{int next,to,from;}edge[MAXN<<1];
int head[MAXN],cnt=1;
void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
#define Pa pair<int,int>
vector<int>BCC[MAXN];
Pa st[MAXN]; int top;
int dfn[MAXN],low[MAXN],dfsn,cut[MAXN],bcc,belong[MAXN],d[MAXN];
void Tarjan(int now,int last)
{
    dfn[now]=low[now]=++dfsn; int son=0;
    for (int i=head[now]; i; i=edge[i].next)
        if (!dfn[edge[i].to]) 
            {
                st[++top]=make_pair(now,edge[i].to);  son++;
                Tarjan(edge[i].to,now); low[now]=min(low[now],low[edge[i].to]); 
                if (dfn[now]<=low[edge[i].to])
                    {
                        cut[now]=1; bcc++; BCC[bcc].clear(); int tnow=-1,tto=-1;
                        while (1) 
                            {
                                tnow=st[top].first,tto=st[top].second; top--;
                                if (belong[tnow]!=bcc) BCC[bcc].push_back(tnow),belong[tnow]=bcc;
                                if (belong[tto]!=bcc) BCC[bcc].push_back(tto),belong[tto]=bcc;
                                if (tnow==now && tto==edge[i].to) break;
                            }
                    }    
            }
        else if (dfn[edge[i].to]<dfn[now] && edge[i].to!=last) 
            st[++top]=make_pair(now,edge[i].to),low[now]=min(low[now],dfn[edge[i].to]);
    if (last<0 && son==1) cut[now]=0;    
}
int main()
{
    N=read(),M=read();
    for (int x,y,i=1; i<=M; i++) x=read(),y=read(),InsertEdge(x,y),d[x]++,d[y]++;
    for (int i=1; i<=N; i++) if (!dfn[i]) Tarjan(i,-1);
    for (int i=1; i<=N; i++) if (!cut[i] && d[i]==M-N+2) tot++;
    printf("%d\n",tot);
    for (int i=1; i<=N; i++) if (!cut[i] && d[i]==M-N+2) printf("%d ",i); puts(""); 
    return 0;
}

曼哈顿距离最小生成树

#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#include<cmath> 
using namespace std; 
int read() 
{ 
    int x=0,f=1; char ch=getchar(); 
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} 
    return x*f; 
} 
#define MAXN 100010 
int N; 
struct PointNode{int x,y,id;}P[MAXN]; 
bool cmpP(PointNode A,PointNode B) {return A.x!=B.x? A.x<B.x : A.y<B.y;} 
struct UnionFind 
{ 
    int Fa[MAXN]; 
    void Init() {for (int i=1; i<=N; i++) Fa[i]=i;} 
    int Find(int x) {if (Fa[x]==x) return x; else return Fa[x]=Find(Fa[x]);} 
    bool Merge(int x,int y) {int f1=Find(x),f2=Find(y); if (f1==f2) return 0; Fa[f1]=f2; return 1;} 
}uf; 
int Dis(PointNode A,PointNode B) {return abs(A.x-B.x)+abs(A.y-B.y);} 
struct EdgeNode{int to,val,from;}edge[MAXN<<2]; 
int cnt; 
void AddEdge(int u,int v,int w) {cnt++; edge[cnt].from=u; edge[cnt].to=v; edge[cnt].val=w;} 
bool cmpE(EdgeNode A,EdgeNode B) {return A.val<B.val;} 
int lowbit(int x) {return x&-x;} 
struct BITNode{int minn,pos; void init() {minn=0x7fffffff; pos=-1;}}bit[MAXN]; 
void Update(int x,int val,int pos) 
{ 
    for (int i=x; i; i-=lowbit(i)) 
        if (val<bit[i].minn) bit[i].minn=val,bit[i].pos=pos; 
} 
int Query(int x,int M) 
{ 
    int minn=0x7fffffff,pos=-1; 
    for (int i=x; i<=M; i+=lowbit(i)) 
        if (bit[i].minn<minn) minn=bit[i].minn,pos=bit[i].pos; 
    return pos; 
}
int num,Ans;
void MST() 
{ 
    int a[MAXN],b[MAXN]; 
    for (int k=0; k<=3; k++) 
        { 
            if (k==1 || k==3) for (int i=1; i<=N; i++) swap(P[i].x,P[i].y); 
                else if (k==2) for (int i=1; i<=N; i++) P[i].x=-P[i].x; 
            stable_sort(P+1,P+N+1,cmpP); 
            for (int i=1; i<=N; i++) 
                a[i]=b[i]=P[i].y-P[i].x; 
            stable_sort(b+1,b+N+1); 
            int M=unique(b+1,b+N+1)-b-1; 
            for (int i=1; i<=M; i++) bit[i].init(); 
            for (int i=N; i>=1; i--) 
                { 
                    int pos=lower_bound(b+1,b+M+1,a[i])-b; 
                    int ans=Query(pos,M); 
                    if (ans!=-1) AddEdge(P[i].id,P[ans].id,Dis(P[i],P[ans])); 
                    Update(pos,P[i].x+P[i].y,i); 
                } 
        } 
    stable_sort(edge+1,edge+cnt+1,cmpE); 
    uf.Init(); 
    for (int i=1; i<=cnt; i++) 
        { 
            int u=edge[i].from,v=edge[i].to; 
            if (uf.Merge(u,v)) Ans+=edge[i].val,num++; 
            if (num==N-1) break; 
        } 
} 
int main() 
{ 
    N=read(); 
    for (int i=1; i<=N; i++) P[i].x=read(),P[i].y=read(),P[i].id=i; 
    MST(); 
    printf("%d\n",Ans); 
    return 0; 
}

数学相关

基础  快速幂&快速乘&逆元&ExGcd

long long quick_pow(long long x,long long y,long long p)
{
    long long re=1;
    for (int i=y; i; i>>=1,x=x*x%p)
        if (i&1) re=re*x%p;
    return re;
}
inline LL Mul(LL x,LL y) {return (x*y-(LL)(x/(long double)P*y+1e-3)*P+P)%P;}
#include<iostream>
#include<cstdio>
using namespace std;
int n,mod,x,y;
void exgcd(int a, int b)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return;
    }
    exgcd(b, a%b);
    int t = x;
    x = y;
    y = t - a/b*y;
}


int main()
{
    //n在模mod意义下的逆元
    scanf("%d%d",&n,&mod);
    exgcd(n,mod);
    printf("%d\n",(x%mod+mod)%mod);
    return 0;
}

//================================
void prework()
{
    memset(flag,0,sizeof(flag));
    flag[1]=1; inv[1]=1;jc[1]=1;//inv为逆元,jc为阶乘
    int cnt=0;
    for (int i=2; i<=maxn; i++)
        {
            jc[i]=jc[i-1]*i%p;
            if (!flag[i])
                prime[++cnt]=i,inv[i]=quick_pow(i,p-2,p);
            for (int j=1; j<=cnt && i*prime[j]<=maxn; j++)
                {
                    flag[i*prime[j]]=1;
                    inv[i*prime[j]]=inv[i]*inv[prime[j]]%p;
                    if (i%prime[j]==0) break;
                }
        }
}
//================================
inv[1]=1;
    for (int i=2; i<=maxn&&i<p; i++)
        inv[i]=(p-p/i)*inv[p%i]%p;
void exgcd(int a, int b)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return;
    }
    exgcd(b, a%b);
    int t = x;
    x = y;
    y = t - a/b*y;
}

拓展BSGS  

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
long long gcd(long long a,long long b)
{
    if (b==0) return a; else return gcd(b,a%b);
}
long long quick_pow(long long x,long long y,long long p)
{
    long long re=1; x%=p; y%=p;
    for (long long i=y; i; i>>=1,x=x*x%p)
        if (i&1) re=re*x%p;
    return re;
}
long long bsgs(long long a,long long b,long long p){
    if(a%=p,b%=p,b==1)return 0;
    long long t=1;long long f,g,delta=0,m=sqrt(p)+1,i;
    for(g=gcd(a,p);g!=1;g=gcd(a,p)){
        if(b%g)return -1;
        b/=g,p/=g,t=t*(a/g)%p,delta++;
        if(b==t)return delta;
    }
    map<long long,long long>hash;
    for(i=0;i<m;i++,b=b*a%p)hash[b]=i;
    for(i=1,f=quick_pow(a,m,p);i<=m+1;i++)
    if(t=t*f%p,hash.count(t))return i*m-hash[t]+delta;
    return -1;
}
int main()
{
    long long a,b,p;
    while (cin>>a>>b>>p)
        {
            //if (a==0 && b==0 && p==0) break;
            long long ans=bsgs(a,b,p);
            if (ans==-1) puts("No Solution");
                    else printf("%lld\n",ans);
        }
    return 0;
}

Lucas定理

int quick_pow(long long a,int b,int p)//快速幂(算逆元)
{
    int ans=1;
    for(int i=b;i;i>>=1,a=(a*a)%p)
        if(i&1)ans=(ans*a)%p;
    return ans;
}
void cs()//初始出阶乘
{
    jc[1][0]=jc[2][0]=jc[3][0]=jc[0][0]=1;//第一维无意义(因题目分成的几个模质数)
    for (int i=0; i<4; i++)
        for (int j=1; j<=pp[i]; j++)
            jc[i][j]=(jc[i][j-1]*j)%pp[i];
}
int C(int n,int m,int p)//组合数
{
    if (n<m) return 0;
    return jc[p][n]*quick_pow(jc[p][m]*jc[p][n-m],pp[p]-2,pp[p])%pp[p];
}
int lucas(int n,int m,int p)//lucas
{
    if (m==0) return 1;
    return C(n%pp[p],m%pp[p],p)*lucas(n/pp[p],m/pp[p],p)%pp[p];
}

拓展lucas定理

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
#define MAXN 100010
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
	while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}

#define Pa pair<LL,LL>
#define MP make_pair
#define X first
#define C second

int N,M,P,w[MAXN];

inline LL Pow(LL x,LL y) {LL re=1; for (LL i=y; i; i>>=1,x=x*x) if (i&1) re=re*x; return re;}
inline LL Pow(LL x,LL y,LL p) {LL re=1; for (LL i=y; i; i>>=1,x=x*x%p) if (i&1) re=re*x%p; return re;}

inline void Exgcd(LL a,LL b,LL &x,LL &y) {if (!b) {x=1,y=0; return;} else Exgcd(b,a%b,y,x),y-=a/b*x;}

inline LL Inv(LL x,LL p) {LL a,b; Exgcd(x,p,a,b); return (a%p+p)%p;}

inline Pa Fac(LL x,LL p,LL c,LL pc)
{
	if (x==1 || !x) return MP(1,0);
	
	int las=x%pc; LL re2=1,re1;
	
	for (int i=1; i<=las; i++) {
		if (!(i%p)) continue;
		re2=re2*i%pc;
	}
	
	if (x>=pc) {
		re1=re2;
		for (int i=las+1; i<pc; i++) {
			if (!(i%p)) continue;
			re1=re1*i%pc;
		}
		re1=Pow(re1,x/pc,pc);
	} else re1=1;
	
	int t=x/p;
	Pa re=Fac(x/p,p,c,pc);
	return MP(re1*re2%pc*re.X%pc,t+re.C);
}

inline LL Lucas(LL n,LL m,LL p,LL c,LL pc)
{	
	Pa n1=Fac(n,p,c,pc),m1=Fac(m,p,c,pc),nm1=Fac(n-m,p,c,pc);
	
	int rc=n1.C-m1.C-nm1.C;
	
	LL re=1;
	re=n1.X*Inv(m1.X,pc)%pc*Inv(nm1.X,pc)%pc;
	
	for (int i=1; i<=rc; i++) re=(re*p)%pc;
	
	return re;
}

int p[MAXN],cnt,ex[MAXN],pex[MAXN];
inline void Divide(int x)
{
	int sx=x;
	for (int i=2; i*i<=sx; i++) {
		if (!(x%i)) {
			p[++cnt]=i;
			while (!(x%i)) ex[cnt]++,x/=i;
			pex[cnt]=Pow(i,ex[cnt]);
		}
	}
	if (x>1) p[++cnt]=x,pex[cnt]=x,ex[cnt]=1;
}

LL an[MAXN];
inline LL CRT(int n,int m)
{
	LL re=0;
	for (int i=1; i<=cnt; i++)
		an[i]=Lucas(n,m,p[i],ex[i],pex[i]);
	
	for (int i=1; i<=cnt; i++)
		(re+=P/pex[i]*Inv((P/pex[i])%pex[i],pex[i])%P*an[i]%P)%=P;
	
	return re;
}

int main()
{
	P=read(); Divide(P);
	
	N=read(),M=read();
	
	LL tot=0;
	for (int i=1; i<=M; i++) w[i]=read(),tot+=w[i];
	
	if (tot>N) return puts("Impossible"),0;
	
	LL ans=CRT(N,tot);
	for (int i=1; i<=M; i++) {
		ans=ans*CRT(tot,w[i])%P;
		tot-=w[i];
	}
	
	printf("%lld\n",ans);
	
	return 0;
}

线性筛欧拉函数&莫比乌斯函数&单个欧拉函数

long long prime[maxn],phi[maxn];
bool flag[maxn]={0};
int n;
void get_phi()
{
    memset(flag,0,sizeof(flag));
    flag[1]=1; 
    int cnt=0;
    for (int i=2; i<=maxn; i++)
        {
            if (!flag[i])
                prime[cnt++]=i,phi[i]=i-1;
            for (int j=0; j<cnt && i*prime[j]<maxn; j++)
                {
                    flag[i*prime[j]]=1;
                    if (i%prime[j]==0)
                        {
                            phi[i*prime[j]]=phi[i]*prime[j];
                            break;
                        }
                    else
                        phi[i*prime[j]]=phi[i]*(prime[j]-1);
                }
        }
}
int prime[100010],tot,mu[100010];bool flag[100010];
void Prework(int x)
{
    flag[1]=1; mu[1]=1;
    for (int i=2; i<=x; i++)
        {
            if (!flag[i]) prime[++tot]=i,mu[i]=-1;
            for (int j=1; j<=tot&&i*prime[j]<=x; j++)
                {
                    flag[i*prime[j]]=1;
                    if (!(i%prime[j])) {mu[i*prime[j]]=0; break;}
                        else mu[i*prime[j]]=-mu[i];
                }
        }
}
int euler_phi(int n)//求单个欧拉函数
{
    int m=(int)sqrt(n+0.5);
    int i,ans=n;
    for(i=2;i<=m;i++)
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0)n/=i;
        }
    if(n>1)ans=ans/n*(n-1);
    return ans;
}

杜教筛 $\phi$前缀和 $\mu$前缀和

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
#define N 5000000
#define P 233333
#define MAXN 250000
LL T,X;
int prime[N+10],cnt,flag[N+10];
LL phi[N+10],mu[N+10];
inline void Euler(int n)
{
	flag[1]=1,phi[1]=1,mu[1]=1;
	for (int i=2; i<=n; i++)
		{
			if (!flag[i]) prime[++cnt]=i,mu[i]=-1,phi[i]=i-1;
			for (int j=1; j<=cnt && i*prime[j]<=n; j++)
				{
					flag[i*prime[j]]=1;
					if (!(i%prime[j]))
						{
							mu[i*prime[j]]=0;
							phi[i*prime[j]]=phi[i]*prime[j];
							break;
						}
					mu[i*prime[j]]=-mu[i];
					phi[i*prime[j]]=phi[i]*(prime[j]-1);
				}
		}
	for (int i=1; i<=n; i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}
#define INF -(1LL<<62)
struct Node{
	int next; LL i,x;
};
struct Hash{
	Node mp[MAXN];
	int head[MAXN],tot;
	inline void Add(LL i,LL x) {int pos=i%P; tot++; mp[tot].i=i; mp[tot].x=x; mp[tot].next=head[pos]; head[pos]=tot;}
	inline LL Find(LL i)
		{
			int pos=i%P;
			for (int j=head[pos]; j; j=mp[j].next)
				if (mp[j].i==i) return mp[j].x;
			return INF;
		}
}Phi,Mu;

inline LL Sumphi(LL x)
{
	if (x<=N) return phi[x];
	else
		{
			LL re=Phi.Find(x);
			if (re!=INF) return re;
		}
	
	LL sum=0;
	for (LL i=2,j; i<=x; i=j+1) j=x/(x/i),sum+=Sumphi(x/i)*(j-i+1);
	
	Phi.Add(x,x*(x+1)/2-sum);
	return x*(x+1)/2-sum;
}

inline LL Summu(LL x)
{
	if (x<=N) return mu[x];
	else
		{
			LL re=Mu.Find(x);
			if (re!=INF) return re;
		}
	
	LL sum=0;
	for (LL i=2,j; i<=x; i=j+1) j=x/(x/i),sum+=Summu(x/i)*(j-i+1);
	
	Mu.Add(x,1LL-sum);
	return 1LL-sum;
}

int main()
{
	Euler(N);
	scanf("%d",&T);
	while (T--)
		{
			scanf("%lld",&X);
			printf("%lld %lld\n",Sumphi(X),Summu(X));
		}
	return 0;
}

中国剩余定理

#include <iostream>
#include<cstdio>

using namespace std;

int Extended_Euclid(int a,int b,int &x,int &y)    //扩展欧几里得算法
{
    int d;
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    d=Extended_Euclid(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

int Chinese_Remainder(int a[],int w[],int len)    //中国剩余定理  a[]存放余数  w[]存放两两互质的数
{
    int i,d,x,y,m,n,ret;
    ret=0;
    n=1;
    for (i=0;i<len;i++)
        n*=w[i];
    for (i=0;i<len;i++)
    {
        m=n/w[i];
        d=Extended_Euclid(w[i],m,x,y);
        ret=(ret+y*m*a[i])%n;
    }
    return (n+ret%n)%n;
}


int main()
{
    int n,i;
    int w[15],b[15],cs[15];
    while (scanf("%d",&n),n)   
    {
        for (i=0;i<n;i++)
        {
            scanf("%d%d%d",&cs[i],&w[i],&b[i]);
        }
        printf("%d\n",Chinese_Remainder(b,w,n));
    }
    return 0;
}

高斯消元&线性基

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 1100
#define eps 1e-5
double a[MAXN][MAXN],x[MAXN];
int N,M,flag; //flag=1 唯一解  0无解  -1不唯一解 
inline void Gauss()
{
    flag=1;
    for (int i=1; i<=M; i++)
        {
            int mx=i;
            for (int j=i+1; j<=N; j++)
                if (abs(a[j][i])>abs(a[mx][i])) mx=j;
            swap(a[i],a[mx]);
            if (abs(a[i][i])<eps) {flag=-1; continue;}
            for (int j=i+1; j<=M+1; j++) a[i][j]/=a[i][i];
            a[i][i]=1;
                    
            for (int j=i+1; j<=N; j++)
                {
                    for (int k=i+1; k<=M+1; k++) 
                        a[j][k]-=a[j][i]*a[i][k];
                    a[j][i]=0;
                }
//            puts("");
//            for (int j=1; j<=N; j++,puts(""))
//                for (int k=1; k<=M+1; k++)
//                    printf("%.1lf   ",a[j][k]);
//            puts("================");
        }
    for (int i=1,f=1; i<=N; i++,f=1)
        {
            for (int j=1; j<=M && f; j++)
                if (abs(a[i][j])>eps) f=0;
            if (abs(a[i][M+1])>eps && f) flag=0;
        }
    if (flag==0) return;
    for (int i=M; i>=1; i--)
        {
            x[i]=a[i][M+1];
            for (int j=i+1; j<=M; j++)
                x[i]-=x[j]*a[i][j];
        }
}
int main()
{
    M=read(),N=read();
    for (int i=1; i<=N; i++)
        for (int j=1; j<=M+1; j++)
            a[i][j]=read();
    Gauss();
    switch (flag)
        {
            case 1: for (int i=1; i<=M; i++) printf("%.2lf\n",x[i]); break;
            case 0: puts("No solutions"); break;
            case -1: puts("Many solutions"); break;    
        }
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
inline LL read()
{
    LL x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int T,N,Q,M,flag,cas;
LL a[100010],lb[100010];
inline void Gauss()
{
    M=0; flag=0; int i;
    for (LL j=1LL<<62; j; j>>=1)
        {
            for (i=M+1; i<=N; i++) 
                if (a[i]&j) break;
            if (i>N) continue;
            swap(a[++M],a[i]);
            for (i=1; i<=N; i++) if (i!=M && a[i]&j)
                a[i]^=a[M];
        }
    if (M!=N) flag=1;
    for (int i=1; i<=M;i++) lb[i]=a[i];
}
int main()
{
    T=read();
    while (T--)
        {
            printf("Case #%d:\n",++cas);
            N=read();
            for (int i=1; i<=N; i++) a[i]=read();
            Gauss();
            LL Num=(1LL<<M);
            Q=read();
            for (int i=1; i<=Q; i++)
                {
                    LL k=read(),ans=0;
                    if (flag) k--;
                    if (k>=Num) {puts("-1"); continue;}
                    if (!k) {puts("0"); continue;}
                    for (int j=1; j<=M; j++)
                        if (k&(1LL<<(M-j))) ans^=lb[j]; 
                    printf("%lld\n",ans);
                }
        }
    return 0;
} 

Pollar_Rho分解&Miller_Rabin判质数

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
long long read()
{
    long long x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
long long e,N,c,r,P,Q;
long long Quick_Mul(long long x,long long y,long long p)
{
    long long re=0;
    for (long long i=y; i; i>>=1,x=(x+x)%p)
        if (i&1) re=(re+x)%p;
    return re;
}
long long Quick_Pow(long long x,long long y,long long p)
{
    long long re=1;
    for (long long i=y; i; i>>=1,x=Quick_Mul(x,x,p))
        if (i&1) re=Quick_Mul(re,x,p);
    return re;
}
void Exgcd(long long a,long long b,long long &x,long long &y)
{
    if (b==0) {x=1; y=0; return;}
    Exgcd(b,a%b,y,x); y-=(a/b)*x;
}
long long GetInv(long long n,long long p)
{
    long long x,y;
    Exgcd(n,p,x,y);
    return (x%p+p)%p;
}
long long Gcd(long long a,long long b)
{
    if (b==0) return a; 
    return Gcd(b,a%b);
}
#define T 10007
long long Pollard_Rho(long long n)
{
    long long x,y,cnt=1,k=2;
    x=rand()%(n-1)+1; y=x;
    while (1)
        {
            cnt++;
            x=(Quick_Mul(x,x,n)+T)%n;
            long long gcd=Gcd(abs(x-y),n);
            if (1<gcd && gcd<n) return gcd;
            if (x==y) return n;
            if (cnt==k) y=x,k<<=1;
        }
}
int main()
{
    srand(T);
    e=read(),N=read(),c=read();
    P=Pollard_Rho(N); Q=N/P;
    r=(P-1)*(Q-1);
    long long Inv=GetInv(e,r);
    printf("%lld %lld",Inv,Quick_Pow(c,Inv,N));
    return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;
long long read()
{
    long long x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
long long X,maxz;
long long gcd(long long a,long long b)
{
    if (b==0) return a;
    return gcd(b,a%b);
}
//long long mul(long long a,long long b,long long p)
//{
//    if (b==0) return 0; if (b==1) return a%p;
//    long long re;
//    re=mul(a,b>>1,p);
//    if ((b&1)==1) return (re+re+a)%p;
//             else return (re+re)%p;
//}
long long mul(long long a,long long b,long long p)
{
    long long tmp=(a*b-(long long)((long double)a/p*b+1e-8)*p);
    return tmp<0?tmp+p:tmp;
}
long long quick_pow(long long a,long long b,long long p)
{
    long long ans=1; a%=p;
    for (long long i=b; i; i>>=1,a=mul(a,a,p))
        if (i&1) ans=mul(ans,a,p);
    return ans;
}
bool check(long long a,long long n,long long r,long long s)
{
    long long ans=quick_pow(a,r,n),p=ans;
    for(int i=1; i<=s; i++)
    {
        ans=mul(ans,ans,n);
        if(ans==1&&p!=1&&p!=n-1)return 1;
        p=ans;
    }
    if(ans!=1)return 1;else return 0;
}
bool Robin_Miller(long long x)
{
    if(x<=1) return 0;
    if(x==2) return 1;
    if(x%2==0) return 0;
    long long r=x-1,s=0;
    while(r%2==0) r/=2,s++;
    for(int i=0; i<20; i++)
        if(check(rand()%(x-1)+1,x,r,s))
            return 0;
    return 1;
}
long long Rho(long long x,long long t)
{
    long long k=2,a=rand()%x,b=a,p=1;
    for(long long i=1; p==1; i++)
    {
        a=(mul(a,a,x)+t)%x;
        p=b>a?b-a:a-b;
        p=gcd(x,p);
        if(i==k) b=a,k+=k;
    }
    return p;
}
void work(long long x)
{
    if(x==1) return;
    if(Robin_Miller(x)){maxz=max(x,maxz);return;}
    long long t=x;
    while(t==x) t=Rho(x,rand()%(x-1)+1);
    work(t); work(x/t);
}
int main()
{
    int n;n=read();
    while (n--)
        {
            X=read(); maxz=0;
            work(X);
            if (maxz==X) puts("Prime");
                else printf("%lld\n",maxz);
        }
    return 0;
}

FFT&NTT

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 400010
#define Pai acos(-1.0)
struct Complex{
    double r,i;
    Complex(double R=0.0,double I=0.0) {r=R,i=I;}
    Complex operator - (const Complex & A) const {return Complex(r-A.r,i-A.i);}
    Complex operator + (const Complex & A) const {return Complex(r+A.r,i+A.i);}
    Complex operator * (const Complex & A) const {return Complex(r*A.r-i*A.i,r*A.i+A.r*i);}
};
Complex A[MAXN],B[MAXN],C[MAXN];
int N,M,a[MAXN],b[MAXN],ans[MAXN],len;
inline void Prework()
{
    len=1;
    while (len<(N+1+M+1)) len<<=1;
    for (int i=0; i<=N; i++) A[i]=Complex(a[i+1],0);
    for (int i=0; i<=M; i++) B[i]=Complex(b[i+1],0);
    for (int i=N+1; i<len; i++) A[i]=Complex(0,0);
    for (int i=M+1; i<len; i++) B[i]=Complex(0,0);
//  for (int i=0; i<len; i++) printf("%d ",(int)(A[i].r+0.5)); puts("");
//  for (int i=0; i<len; i++) printf("%d ",(int)(B[i].r+0.5)); puts("");
}
inline void Rader(Complex *x)
{
    for (int i=1,j=len>>1,k; i<len-1; i++)
        {
            if (i<j) swap(x[i],x[j]);
            k=len>>1;
            while (j>=k) j-=k,k>>=1;
            if (j<k) j+=k;
        }
}
inline void DFT(Complex *x,int opt)
{
    Rader(x);
    for (int h=2; h<=len; h<<=1)
        {
            Complex Wn( cos(opt*2*Pai/h),sin(opt*2*Pai/h) );
            for (int i=0; i<len; i+=h)
                {
                    Complex W(1,0);
                    for (int j=i; j<i+h/2; j++)
                        {
                            Complex u=x[j],t=W*x[j+h/2];
                            x[j]=u+t; x[j+h/2]=u-t;
                            W=W*Wn;
                        }
                }
        }
    if (opt==-1)
        for (int i=0; i<len; i++) x[i].r/=len;
}
inline void FFT(Complex *A,Complex *B)
{
    DFT(A,1); DFT(B,1);
    for (int i=0; i<len; i++) C[i]=A[i]*B[i];
    DFT(C,-1);
    for (int i=0; i<len; i++) ans[i]=(int)(C[i].r+0.5);
}
int main()
{
    N=read(),M=read();
    for (int i=1; i<=N+1; i++) a[i]=read();
    for (int i=1; i<=M+1; i++) b[i]=read();
    Prework();
    FFT(A,B);
    for (int i=0; i<=N+M; i++) printf("%d ",ans[i]); puts("");
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 300010
#define LL long long
#define P ((479<<21)+1)
#define G 3
int N,M,a[MAXN],b[MAXN],len;
LL wn[MAXN],A[MAXN],B[MAXN],C[MAXN];
inline LL Pow(LL x,LL y)
{
    LL re=1;
    for (int i=y; i; i>>=1,x=x*x%P)
        if (i&1) re=re*x%P;
    return re;
}
inline LL Inv(LL x) {return Pow(x,P-2);}
inline void Prework()
{
    len=1;
    while (len<(N+1+M+1)) len<<=1;
    for (int i=0; i<=N; i++) A[i]=a[i+1];
    for (int i=0; i<=M; i++) B[i]=b[i+1];
    for (int i=N+1; i<len; i++) A[i]=0;
    for (int i=M+1; i<len; i++) B[i]=0; 
    for (int i=0; i<21; i++) wn[i]=Pow(G,(P-1)/(1<<i));
}
inline void Rader(LL *x)
{
    for (int i=1,j=len>>1,k; i<len-1; i++)
        {
            if (i<j) swap(x[i],x[j]);
            k=len>>1;
            while (j>=k) j-=k,k>>=1;
            if (j<k) j+=k;
        }
}
inline void DFT(LL *x,int opt)
{
    Rader(x);
    for (int h=2,id=0; h<=len; h<<=1)
        {
            LL Wn=wn[++id];
            for (int i=0; i<len; i+=h)
                {
                    LL W=1;
                    for (int j=i; j<i+h/2; j++)
                        {
                            LL u=x[j]%P,t=W*x[j+h/2]%P;
                            x[j]=(u+t)%P; x[j+h/2]=(u-t+P)%P;
                            W=W*Wn%P;
                        }
                }
        }
    if (opt==-1)
        {
            for (int i=1; i<len/2; i++) swap(x[i],x[len-i]);
            for (int i=0; i<len; i++)
                x[i]=x[i]*Inv(len)%P;
        }
}
inline void NTT(LL *A,LL *B)
{
    DFT(A,1); DFT(B,1);
    for (int i=0; i<len; i++) C[i]=A[i]*B[i]%P;
    DFT(C,-1);
}
int main()
{
    N=read(),M=read();
    for (int i=1; i<=N+1; i++) a[i]=read();
    for (int i=1; i<=M+1; i++) b[i]=read();
    Prework();
    NTT(A,B);
    for (int i=0; i<=N+M; i++) printf("%d ",C[i]); puts("");
    return 0;
}

字符串相关

Hash

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int N,L,SS,ans=0;
unsigned long long bin[210],hash[30010][210],HASH[30010];
char S[30010][210];
#define BASE 131
void Hash(char *s,unsigned long long t)
{
    for (int i=1; i<=L; i++)
        hash[t][i]=hash[t][i-1]*BASE+s[i];
}
unsigned long long GetHash(unsigned long long t,int l)
{
    return hash[t][L]-hash[t][l]*bin[L-l]+hash[t][l-1]*bin[L-l+1];
}
int main()
{
    scanf("%d%d%d",&N,&L,&SS);
    bin[0]=1;
    for (int i=1; i<=L; i++) bin[i]=bin[i-1]*BASE;
    for (int i=1; i<=N; i++)
        scanf("%s",S[i]+1),Hash(S[i],i);
    for (int i=1; i<=L; i++)
        {
            for (int j=1; j<=N; j++)
                HASH[j]=GetHash(j,i);
            sort(HASH+1,HASH+N+1); HASH[N+1]=0;
            for (int pre=1,cnt,j=1; j<=N+1; j++)
                if (HASH[j]!=HASH[pre])
                    cnt=j-pre,ans+=cnt*(cnt-1)/2,pre=j;
        }
    printf("%d\n",ans);
    return 0;
}

KMP

inline void GetNext()
{
	Next[1]=0;
	for (int j=0,i=2; i<=l[1]; i++)
		{
			while (j && s[1][j+1]!=s[1][i]) j=Next[j];
			if (s[1][j+1]==s[1][i]) j++;
			Next[i]=j;
		}
}
inline int KMP(int x,int st)
{
	int len=0;
	for (int i=1,j=st-1; i<=l[x]-1; i++)
		{
			while (j>=st && s[x][i]!=s[1][j+1]) j=Next[j];
			if (j<st) j=st-1;
			if (s[1][j+1]==s[x][i]) j++;
			len=max(len,j-st+1);
			if (j==l[1]-1) break;
		}
	return len;
}

AC自动机

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define MAXN 1000100
int K,N,loc[MAXN],visit[MAXN];
struct EdgeNode{int next,to;}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
char S[MAXN];
namespace FailTree
{
    int son[MAXN][27],end[MAXN],sz=1,fail[MAXN];
#define id(str) str-'a'+1
    inline int Insert(int x,char str[])
    {
        int len=strlen(str+1),now=1;
        for (int i=1; i<=len; i++)
            if (son[now][id(str[i])]) now=son[now][id(str[i])];
                else son[now][id(str[i])]=++sz,now=sz;
        end[now]=1; loc[x]=now;
    }
    queue<int>q;
    inline void Getfail()
    {
        q.push(1);
        while (!q.empty())
            {
                int now=q.front(); q.pop();
                for (int i=1; i<=26; i++)
                    if (son[now][i])
                        {
                            int fa=fail[now];
                            while (fa && !son[fa][i]) fa=fail[fa];
                            fail[son[now][i]]=fa? son[fa][i]:1;
                            q.push(son[now][i]);
                        }
            }
        for (int i=1; i<=sz; i++) InsertEdge(fail[i],i);
    }
}
using namespace FailTree;
namespace Divide
{
    int pl[MAXN],pr[MAXN],dfn,tree[MAXN<<1];
    inline void DFS(int now,int last)
    {
        pl[now]=++dfn;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last)
                DFS(edge[i].to,now);
        pr[now]=++dfn;
    }
    inline int lowbit(int x) {return x&-x;}
    inline void Modify(int pos,int D) {for (int i=pos; i<=dfn; i+=lowbit(i)) tree[i]+=D;}
    inline int Query(int pos) {int re=0; for (int i=pos; i; i-=lowbit(i)) re+=tree[i]; return re;}
    inline int Calc(char str[])
    {
        int len=strlen(str+1),ans=0,now=1;
        for (int i=1; i<=len; i++)
            {
                while (now && !son[now][id(str[i])]) now=fail[now];
                now=now? son[now][id(str[i])]:1;
                ans+=Query(pl[now]);
            }
        return ans;
    }
    inline void Change(int x,int D)
    {
        if (visit[x] && D>0) return;
        if (!visit[x] && D<0) return;
        visit[x]^=1;
        Modify(pl[loc[x]],D); Modify(pr[loc[x]],-D);
    }
}
using namespace Divide;
int main()
{
    scanf("%d%d",&K,&N);
    for (int i=1; i<=N; i++) scanf("%s",S+1),Insert(i,S);
    Getfail(); DFS(1,0);
    for (int i=1; i<=N; i++) Modify(pl[loc[i]],1),Modify(pr[loc[i]],-1),visit[i]=1;
    while (K--)
        {
            char opt=getchar(); int x; 
            while (opt!='+' && opt!='-' && opt!='?') opt=getchar();
            switch (opt)
                {
                    case '+' : scanf("%d",&x); Change(x,1); break;
                    case '-' : scanf("%d",&x); Change(x,-1); break;
                    case '?' : scanf("%s",S+1); printf("%d\n",Calc(S)); break;
                }
        }
    return 0;
}

Manacher

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 50010<<1
int n,len,mx,id,p[maxn],cnt;
char S[maxn>>1],s[maxn];
struct TreeNode
{
    int a[maxn];
    void init() {memset(a,127,sizeof(a));}
    int lowbit(int x) {return x&(-x);}
    int Query(int loc)
        {
            if (!loc) return 0;
            int x=0x7fffffff;
            for (int i=loc; i<=n; i+=lowbit(i))
                x=min(x,a[i]);
            return x;
        }
    void Change(int loc,int D)
        {
            for (int i=loc; i; i-=lowbit(i))
                a[i]=min(a[i],D);
        }
}Tree;
void PreWork()
{
    cnt=0; mx=0; id=0;
    Tree.init(); memset(p,0,sizeof(p));
    n=strlen(S+1); len=n<<1|1;
    s[0]='$'; s[1]='#'; s[len+1]='%';
    for (int i=1; i<=n; i++)
        s[i<<1]=S[i],s[i<<1|1]='#';
}
struct HWCNode
{
    int l,r;
    bool operator < (const HWCNode & A) const 
        {return r<A.r;}
}Line[maxn];
void Manacher()
{
    PreWork();
    for (int i=1; i<=len; i++)
        {
            if (mx>i) p[i]=min(p[id*2-i],mx-i);
                else p[i]=1;
            while (s[i-p[i]]==s[p[i]+i]) p[i]++;
            int x=(i-p[i])/2+1,y=(i+p[i])/2-1;
            if (x<=y) Line[++cnt].l=x,Line[cnt].r=y;
            if (p[i]+i>mx) mx=p[i]+i,id=i;
        }
}
int DP()
{
    int ans=0x7fffffff;
    sort(Line+1,Line+cnt+1);
    for (int i=1; i<=cnt; i++)
        {
            int D=Tree.Query(Line[i].l-1)+1;
            Tree.Change(Line[i].r,D);
            if (Line[i].r==n) ans=min(ans,D);
        }
    return ans-1;
}
int main()
{
    while (scanf("%s",S+1)!=EOF)
        Manacher(),printf("%d\n",DP());
    return 0;
}

后缀数组

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 100010
int N,K,a[MAXN];
int R[MAXN],SA[MAXN],height[MAXN],rank[MAXN],t1[MAXN],t2[MAXN],st[MAXN];
inline void Sort(int *x,int *y,int *sa,int L,int M)
{
    for (int i=0; i<=M; i++) st[i]=0;
    for (int i=0; i<L; i++) st[x[y[i]]]++;
    for (int i=1; i<=M; i++) st[i]+=st[i-1];
    for (int i=L-1; i>=0; i--) sa[--st[x[y[i]]]]=y[i];
}
inline void DA(int *r,int *sa,int L,int M)
{
    int *x=t1,*y=t2,*t,i,j,p;
    for (int i=0; i<L; i++) x[i]=r[i],y[i]=i;
    Sort(x,y,sa,L,M);
    for (j=1,p=1; j<L && p<L; j<<=1,M=p-1)
        {
            for (p=0,i=L-j; i<L; i++) y[p++]=i;
            for (i=0; i<L; i++) if (sa[i]>=j) y[p++]=SA[i]-j;
            Sort(x,y,sa,L,M);
            for (t=x,x=y,y=t,i=1,x[sa[0]]=0,p=1; i<L; i++)
                x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]? p-1:p++;
        }
}
inline void Height(int *r,int *sa,int *rank,int *h,int L)
{
    h[1]=0;
    for (int i=1; i<=L; i++) rank[sa[i]]=i;
    for (int i=1,k=0,j; i<=L; h[rank[i++]]=k)
        for (k? --k:k=0,j=sa[rank[i]-1]; r[j+k]==r[i+k]; k++);
}
int log_2[MAXN],dp[MAXN][21];
inline void St(int L)
{
    log_2[0]=-1;
    for (int i=1; i<=L; i++)
        if (i&(i-1))
            log_2[i]=log_2[i-1];
        else
            log_2[i]=log_2[i-1]+1;
    for (int i=0; i<=L; i++) dp[i][0]=height[i+1];
    for (int j=1; (1<<j)<=L; j++)
        for (int i=0; i+(1<<j)-1<=L; i++)
            dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
inline int RMQ(int l,int r) {int k=log_2[r-l]; return min(dp[l][k],dp[r-(1<<k)][k]);}
inline int LCP(int l,int r) {l=rank[l],r=rank[r]; if (l>r) swap(l,r); return RMQ(l,r);}
int ls[MAXN];
int main()
{
    N=read(),K=read();
    for (int i=1; i<=N; i++) a[i]=read();
    for (int i=1; i<=N-1; i++) ls[i]=R[i]=a[i+1]-a[i];
    for (int i=1; i<=N-1; i++) R[N+i]=R[N-1-i+1];
    sort(ls+1,ls+N-1+1);
    int mx=unique(ls+1,ls+N-1+1)-ls-1;
//  for (int i=1; i<=2*N-1; i++) printf("%d  ",R[i]); puts("");
    for (int i=1; i<=2*N-1; i++) R[i]=lower_bound(ls+1,ls+mx+1,R[i])-ls;
    R[N]=mx+1;
//  for (int i=1; i<=2*N-1; i++) printf("%d  ",R[i]); puts("");
    DA(R,SA,2*N-1+1,mx+1); Height(R,SA,rank,height,2*N-1); St(2*N-1);
    LL ans=0;
    for (int len=1; len*2+K<=N-1; len++)
        {
            int pre=0,suf=0;
            for (int i=1; i+len+K<=N-1; i+=len)
                {
                    suf=min(len,LCP(i,i+len+K));
                    if (i>1) pre=min(len-1,LCP(2*N-1-i+1+1,2*N-1-(i+len+K)+1+1)); else pre=0;
//                  printf("%d  %d  %d  %d->",i,i+len+K,2*N-1-i+1,2*N-1-(i+len+K)+1);
                    if (suf+pre>=len) ans+=(LL)(suf+pre-len+1);
//                  printf("%d   %d   %d   %d   %I64d\n",i,len,pre,suf,ans);
                }
        }
    printf("%lld\n",ans);
    return 0;
}

后缀自动机

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 1000010
char S[MAXN<<1];
int N,Q;
namespace SAM
{
    int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1],size[MAXN<<1];
    int last,sz=1,root=1;
    inline void Init() {last=root;}
    inline void Extend(int c)
    {
        int cur=++sz,p=last;
        len[cur]=len[p]+1; size[cur]=1;
        while (p && !son[p][c]) son[p][c]=cur,p=par[p];
        if (!p) par[cur]=root;
        else
            {
                int q=son[p][c];
                if (len[p]+1==len[q]) par[cur]=q;
                else
                    {
                        int nq=++sz;
                        memcpy(son[nq],son[q],sizeof(son[nq]));
                        len[nq]=len[p]+1;
                        par[nq]=par[q];
                        while (p && son[p][c]==q) son[p][c]=nq,p=par[p];
                        par[cur]=par[q]=nq;
                    }
            }
        last=cur;
    }
    inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(S[i]-'a'+1);}
    int st[MAXN],id[MAXN<<1];
    inline void Pre()
    {
        for (int i=1; i<=sz; i++) st[len[i]]++;
        for (int i=1; i<=N; i++) st[i]+=st[i-1];
        for (int i=1; i<=sz; i++) id[st[len[i]]--]=i;
        for (int i=sz; i>=1; i--)
            size[par[id[i]]]+=size[id[i]];
    }
    int flag[MAXN<<1];
    inline void Query()
    {
        int now=root,L=0,ans=0;
        for (int i=1; i<=N+N; i++)
            {
                int c=S[i]-'a'+1;
                if (son[now][c]) L++,now=son[now][c];
                    else
                        {
                            while (now && !son[now][c]) now=par[now];
                            if (!now)
                                now=root,L=0;
                            else
                                L=len[now]+1,now=son[now][c];
                        }
                if (i>N && L>=N)
                    {
                        int tmp=now;
                          while (tmp && !(N>=len[par[tmp]]+1 && N<=len[tmp]))
                            tmp=par[tmp];
                        if (!tmp) tmp=root;
                        if (flag[tmp]!=Q+1) ans+=size[tmp],flag[tmp]=Q+1;
                    }
            }
        printf("%d\n",ans);
    }
}using namespace SAM;
int main()
{
    scanf("%s",S+1); N=strlen(S+1);
    SAM::Build(); SAM::Pre();
    scanf("%d",&Q);
    while (Q--)
        {
            scanf("%s",S+1); N=strlen(S+1);
            for (int i=1; i<=N; i++) S[N+i]=S[i];
            SAM::Query();
        }
    return 0;
}

计算几何

平面计算几何合集

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<string>
#include<bitset>
#include<iomanip>
#define INF 1000000000
#define fi first
#define se second
#define N 100005
#define debug(x) cerr<<#x<<"="<<x<<endl
#define MP(x,y) make_pair(x,y)
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
typedef long double Double;
struct Vector
{
    double x,y;
    Vector(double X=0,double Y=0) {x=X,y=Y;}
};
struct Line
{
    Point P;
    Vector v;
    double ang;//ang为极角 
    Line() {}
    Line(Point P,Vector v):P(P),v(v) {ang=atan2(v.y,v.x);}
    bool operator<(const Line &L) const {return ang<L.ang;}
};
//向量/点、直线的存储 
typedef Vector Point;
typedef vector<Point> Polygon;
const double eps=1e-12;
const double pi=acos(-1.0);
//初始化
Vector operator + (Vector A,Vector B) {return ((Vector){A.x+B.x,A.y+B.y});}
Vector operator - (Vector A,Vector B) {return ((Vector){A.x-B.x,A.y-B.y});}
Vector operator * (Vector A,double p) {return ((Vector){A.x*p,A.y*p});}
Vector operator / (Vector A,double p) {return ((Vector){A.x/p,A.y/p});}
bool operator < (const Vector& a,const Vector& b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool operator == (const Vector& a,const Vector& b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
//重载一下相关运算符 
int dcmp(double x) {if(fabs(x)<eps) return 0; else return x<0? -1:1;}
//精度控制
double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;}
//向量点积 
double Len(Vector A) {return sqrt(Dot(A,A));}
//求向量模长 
double Angle(Vector A,Vector B) {return acos(Dot(A,B)/Len(A)/Len(B));}
//求向量间夹角 
double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
//向量叉积 
double Area2(Point A,Point B,Point C) {return Cross(B-A,C-A);}
//求平行四边形面积
Vector Rotate(Vector A,double rad) {return ((Vector){A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad)});}
//向量旋转(考虑成:对一个向量拆分成XY坐标系上的两个向量并分别旋转来计算) 
Vector Normal(Vector A) {double L=Len(A); return Vector(-A.y/L,A.x/L);}
//计算单位法向量,其中A应该是非零向量 
bool OnLeft(Line L,Point p) {return dcmp(Cross(L.v,p-L.P))>=0;}
//利用叉积去判断点在直线的左/右 
Point GLI(Point P,Vector v,Point Q,Vector w) {Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t;}
Point GLI(Line a,Line b) {Vector u=a.P-b.P; double t=Cross(b.v,u)/Cross(a.v,b.v);return a.P+a.v*t;}
//直线与直线的交点,考虑面积法  
double DisTL(Point P,Point A,Point B) {Vector v1=B-A,v2=P-A; return fabs(Cross(v1,v2)/Len(v1));}
//点到直线的距离 
double DisTS(Point P,Point A,Point B)
{
    if(A==B) return Len(P-A);
    Vector v1=B-A, v2=P-A, v3=P-B;
    if(dcmp(Dot(v1,v2))<0) return Len(v2);
    else if(dcmp(Dot(v1,v3))>0) return Len(v3);
    else return fabs(Cross(v1,v2))/Len(v1);
}
//点到线段的距离(需要进行判断,如果点到直线的垂线段垂足在线段上,则可以直接返回与直线交点,否则为靠近的点得距离) 
bool OnSegment(Point P,Point A,Point B) {return dcmp(DisTL(P,A,B))==0&&dcmp(Dot(P-A,P-B))<0&&!(P==A)&&!(P==B);}
//判断是否在线段上 
double PolygonArea(Point* p,int n)
{
    double area=0;
    for(int i=1;i<n-1;i++)
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return area/2;
}
double PolygonArea(Polygon p)
{
    double area=0;
    int n=p.size();
    for(int i=1;i<n-1;i++)
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return area/2;
}
//求多边形面积(应用三角剖分)经证明可以随意选基准点 
int PInP(Point p,Point* poly,int n)
{
    int wn=0,k,d1,d2;
    for(int i=0;i<n;i++)
    {
        if(dcmp(DisTS(p,poly[i],poly[(i+1)%n])==0)) return -1;
        k=dcmp(Cross(poly[(i+1)%n]-poly[i],p-poly[i]));
        d1=dcmp(poly[i].y-p.y);
        d2=dcmp(poly[(i+1)%n].y-p.y);
        if(k>0&&d1<=0&&d2>0) wn++;
        if(k<0&&d2<=0&&d1>0) wn--;
    }
    if(wn) return 1;
    else return 0;
}
//判断点是否在多面型内(射线法) 
int ConvexHull(Point* p,int n,Point* ch) //have no three point on one line
{
    sort(p,p+n);
    int k,i,m=0;
    for(i=0;i<n;i++)
    {
        while(m>1&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--;
        ch[m++]=p[i];
    }
    k=m;
    for(i=n-2;i>=0;i--)
    {
        while(m>k&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--;
        ch[m++]=p[i];
    }
    if(n>1) m--;
    return m;
}
//Graham扫描法求凸包 
double Rotating_calipers(Point* ch,int n)
{
    if(n==1) return 0;
    if(n==2) return Len(ch[0]-ch[1]);
    int now=1,i;
    double ans=0;
    ch[n]=ch[0];
    for(i=0;i<n;i++)
    {
        while(dcmp(DisTL(ch[now],ch[i],ch[i+1])-DisTL(ch[now+1],ch[i],ch[i+1]))<=0)
            now=(now+1)%n;
        ans=max(ans,Len(ch[now]-ch[i]));
        ans=max(ans,Len(ch[now]-ch[i+1]));
    }
    return ans;
}
//旋转卡壳求平面最远点对距离 
double Rotating_calipers2(Point* p,Point* q,int n,int m) 
{
    int x=0,y=0,i;
    double ans=1e10,t;
    for(i=0;i<n;i++)
        x=(p[i].y<p[x].y)?i:x;
    for(i=0;i<m;i++)
        y=(q[i].y<q[y].y)?i:y;
    p[n]=p[0];
    q[m]=q[0];
    for(i=0;i<n;i++)
    {
        while((t=dcmp(Cross(p[x]-p[x+1],q[y+1]-q[y])))<0)
            y=(y+1)%m;
        if(t==0)
        {
            ans=min(ans,DisTS(p[x],q[y+1],q[y]));
            ans=min(ans,DisTS(p[x+1],q[y+1],q[y]));
            ans=min(ans,DisTS(q[y],p[x],p[x+1]));
            ans=min(ans,DisTS(q[y+1],p[x],p[x+1]));
        }
        else
            ans=min(ans,DisTS(q[y],p[x],p[x+1]));
        x=(x+1)%n;
    }
    return ans;
}
//旋转卡壳计算最小凸包之间的距离 (必须做两次这个过程) 
Polygon CutPolygon(Polygon poly,Point A,Point B)  //get the left of A->B
{
    Polygon newpoly;
    Point C,D,ip;
    int n=poly.size(),i;
    for(i=0;i<n;i++)
    {
        C=poly[i];
        D=poly[(i+1)%n];
        if(dcmp(Cross(B-A,C-A))>=0)
            newpoly.push_back(C);
        if(dcmp(Cross(B-A,D-C))!=0)
        {
            ip=GLI(A,B-A,C,D-C);
            if(OnSegment(ip,C,D))
                newpoly.push_back(ip);
        }
    }
    return newpoly;
}
//直线切凸包(半平面交) 
void InitPolygon(Polygon &poly,double inf)
{
    poly.clear();
    poly.push_back((Point){-inf,-inf});
    poly.push_back((Point){inf,-inf});
    poly.push_back((Point){inf,inf});
    poly.push_back((Point){-inf,inf});
}

int Halfplane_Intersection(Line* L,int n,Point* poly)
{
    sort(L,L+n);

    int first,last,i;
    Point *p=new Point[n];
    Line *q=new Line[n];
    q[first=last=0]=L[0];
    for(i=1;i<n;i++)
    {
        while(first<last&&!OnLeft(L[i],p[last-1]))
            last--;
        while(first<last&&!OnLeft(L[i],p[first]))
            first++;
        q[++last]=L[i];
        if(dcmp(Cross(q[last].v,q[last-1].v)/Len(q[last].v))==0)
        {
            last--;
            if(OnLeft(q[last],L[i].P))
                q[last]=L[i];
        }
        if(first<last)
            p[last-1]=GLI(q[last-1],q[last]);
    }
    while(first<last&&!OnLeft(q[first],p[last-1]))
        last--;
    if(last-first<=1) return 0;
    p[last]=GLI(q[last],q[first]);

    int m=0;
    for(i=first;i<=last;i++) poly[m++]=p[i];
    return m;
}
//半平面交(-InitPolygon先初始化一个极大的框) 
Point Center_of_gravity(Point A,Point B,Point C)
{
    Point P=(A+B)/2,Q=(A+C)/2;
    Vector v=Rotate(B-A,pi/2),w=Rotate(C-A,pi/2);
    if(dcmp(Len(Cross(v,w)))==0)//这是三点一线的情况
    {
        if(dcmp(Len(A-B)+Len(B-C)-Len(A-C))==0)
            return (A+C)/2;
        if(dcmp(Len(A-C)+Len(B-C)-Len(A-B))==0)
            return (A+B)/2;
        if(dcmp(Len(A-B)+Len(A-C)-Len(B-C))==0)
            return (B+C)/2;
    }
    return GLI(P,v,Q,w);
}
//求三角形外心(包含特判三点一线的情况) 
double Min_Cover_Circle(Point *p,int n,Point &c)
{
    random_shuffle(p,p+n);
    c=p[0];
    double r=0;
    int i,j,k;
    for(i=1;i<n;i++)
        if(dcmp(Len(c-p[i])-r)>0)
        {
            c=p[i],r=0;
            for(j=0;j<i;j++)
                if(dcmp(Len(c-p[j])-r)>0)
                {
                    c=(p[i]+p[j])/2;
                    r=Len(c-p[i]);
                    for(k=0;k<j;k++)
                        if(dcmp(Len(c-p[k])-r)>0)
                        {
                            c=Center_of_gravity(p[i],p[j],p[k]);
                            r=Len(c-p[i]);
                        }
                }
        }
    return r;
}
//最小圆覆盖(随机增量法)  c为圆心,返回值为r 
int main()
{
    return 0;
}

辛普森积分

#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#include<cmath> 
using namespace std; 
#define MAXN 1010 
double alpha; 
int N,num; 
#define INF 1e12 
#define eps 1e-5 
struct Point 
{ 
    double x,y; 
    Point (double X=0,double Y=0) {x=X; y=Y;} 
}; 
struct Circle 
{ 
    double r; 
    Point c; 
    Circle(Point C=(Point){0,0},double R=0) {c=C; r=R;} 
}C[MAXN]; 
struct Line 
{ 
    Point s,t; 
    double k,b; 
    Line(Point S=(Point){0,0},Point T=(Point){0,0})  
        { 
            s=S,t=T; 
            if (s.x>t.x) swap(s,t); 
            k=(s.y-t.y)/(s.x-t.x); 
            b=s.y-k*s.x; 
        } 
    double f(double x) {return k*x+b;} 
}l[MAXN]; 
int dcmp(double x) {if (fabs(x)<eps) return 0; return x<0? -1:1;} 
double F(double x) 
{ 
    double re=0; 
    for (int i=1; i<=N; i++) //枚举圆是否与扫描线有交
        { 
            double d=fabs(x-C[i].c.x); 
            if (dcmp(d-C[i].r)>0) continue; 
            double len=2*sqrt(C[i].r*C[i].r-d*d); 
            re=max(re,len);  
        } 
    for (int i=1; i<=num; i++) //枚举公切线
        if (x>=l[i].s.x && x<=l[i].t.x) re=max(re,2*l[i].f(x)); 
    return re; 
} //利用扫描线去判断
double Calc(double l,double r) {double mid=(l+r)/2; return (F(l)+F(r)+F(mid)*4)*(r-l)/6;} 
double Simpson(double l,double r,double now) 
{ 
    double mid=(l+r)/2; 
    double x=Calc(l,mid),y=Calc(mid,r); 
    if (!dcmp(now-x-y)) return now; 
    else return Simpson(l,mid,x)+Simpson(mid,r,y); 
} 
void Solve() 
{ 
    double L=INF,R=-INF; 
    for (int i=1; i<=N+1; i++) 
        L=min(L,C[i].c.x-C[i].r),R=max(R,C[i].c.x+C[i].r); 
//  printf("%lf\n%lf\n",L,R); 
    for (int i=1; i<=N; i++) 
        { 
            double d=C[i+1].c.x-C[i].c.x;  
            if (dcmp(d-fabs(C[i].r-C[i+1].r))<0) continue; //特判小圆被大圆覆盖的情况
            double sina=(C[i].r-C[i+1].r)/d,cosa=sqrt(1-sina*sina); 
            l[++num]=(Line){(Point){C[i].c.x+C[i].r*sina,C[i].r*cosa},(Point){C[i+1].c.x+C[i+1].r*sina,C[i+1].r*cosa}}; 
        } 
    printf("%.2lf\n",Simpson(L,R,Calc(L,R))); 
} 
int main() 
{ 
    scanf("%d%lf",&N,&alpha); 
    double h,r; 
    for (int i=1; i<=N+1; i++) 
        scanf("%lf",&h), 
        C[i]=(Circle){((Point){(h/tan(alpha))+C[i-1].c.x,0}),0}; 
    for (int i=1; i<=N; i++) 
        scanf("%lf",&r),C[i].r=r; 
//  for (int i=1; i<=N+1; i++) 
//      printf("%d     %.2lf     %.2lf\n",i,C[i].c.x,C[i].r); 
    Solve(); 
    return 0; 
}

花式套路

点分治

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
#define LL long long
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 100010
int N,M;
map<LL,LL>hash;
LL ans;
namespace Math
{
    LL power[MAXN],Inv[MAXN];
    inline LL Gcd(LL a,LL b) {if (!b) return a; else return Gcd(b,a%b);}
    inline void ExGcd(LL a,LL b,LL &x,LL &y) {if (!b) {x=1,y=0; return;} ExGcd(b,a%b,y,x); y-=(a/b)*x;}
    inline LL inv(LL X) {LL x,y; ExGcd(X,M,x,y); return (x%M+M)%M;}
    inline LL Pow(LL x,LL y) {LL re=1; for (LL i=y; i; i>>=1,x=x*x%M) if (i&1) re=re*x%M; return re;}
}
using namespace Math;
namespace TreeDivide
{
    struct EdgeNode{int next,to,val;}edge[MAXN<<1];
    int head[MAXN],cnt=1; 
    inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].val=w;}
    inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
    int size[MAXN],f[MAXN],visit[MAXN],root,deep[MAXN],Sz;
    LL Dig[MAXN];
    inline void Getroot(int x,int last)
    {
        size[x]=1,f[x]=0;
        for (int i=head[x]; i; i=edge[i].next)
            if (!visit[edge[i].to] && edge[i].to!=last)
                {
                    Getroot(edge[i].to,x);
                    size[x]+=size[edge[i].to];
                    f[x]=max(f[x],size[edge[i].to]);
                }
        f[x]=max(f[x],Sz-f[x]);
        if (f[x]<f[root]) root=x;
    }
    inline void DFS(int now,int last)
    {
        LL D=(((M-Dig[now])+M)%M*Inv[deep[now]])%M; hash[D]++;
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last && !visit[edge[i].to])
                deep[edge[i].to]=deep[now]+1,
                Dig[edge[i].to]=(Dig[now]*10%M+edge[i].val)%M,
                DFS(edge[i].to,now);
    }
    inline LL Get(int now,int last)
    {
        LL re=hash[Dig[now]];
        for (int i=head[now]; i; i=edge[i].next)
            if (edge[i].to!=last && !visit[edge[i].to])
                Dig[edge[i].to]=(edge[i].val*power[deep[now]]%M+Dig[now])%M,
                deep[edge[i].to]=deep[now]+1,
                re+=Get(edge[i].to,now);
        return re;
    }
    inline void Divide(int now)
    {
        visit[now]=1;
        hash.clear(); hash[0]--;
        Dig[now]=0LL,deep[now]=0;
        DFS(now,0);
        ans+=Get(now,0);
        for (int i=head[now]; i; i=edge[i].next)
            if (!visit[edge[i].to])
                hash.clear(),hash[0]--,
                Dig[edge[i].to]=edge[i].val%M,deep[edge[i].to]=1,
                DFS(edge[i].to,now),
                ans-=Get(edge[i].to,now);
        for (int i=head[now]; i; i=edge[i].next)
            if (!visit[edge[i].to])
                Sz=size[edge[i].to],f[root=0]=N,
                Getroot(edge[i].to,now),Divide(root);
    }
}
using namespace TreeDivide;
int main()
{
    N=read(),M=read();
    for (int x,y,z,i=1; i<=N-1; i++) x=read()+1,y=read()+1,z=read(),InsertEdge(x,y,z);
    for (int i=0; i<=N; i++) power[i]=Pow(10,i),Inv[i]=inv(power[i]);
    Sz=N; f[root=0]=N+1; 
    Getroot(1,0); Divide(root);
    printf("%I64d\n",ans);
    return 0;
}

CDQ分治

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 200010
int N,cnt;
struct QNode{
    int opt,id,x,y,v,as;
    bool operator < (const QNode & A) const
        {
            return x<A.x;
        }
        //{return (x==A.x&&y==A.y)? opt<A.opt:(x==A.x? y<A.y:x<A.x);}
}Q[MAXN<<2];
int tree[500010]; 
inline int lowbit(int x) {return x&-x;}
inline void Modify(int x,int d) { for (int i=x; i<=N; i+=lowbit(i)) tree[i]+=d;}
inline int Query(int x) {int re=0; for (int i=x; i; i-=lowbit(i)) re+=tree[i]; return re;}
int ans[MAXN];
inline void CDQ(int l,int r)
{   
    if (l==r) return;
//  printf("begin<%d %d>\n",l,r);
    int mid=(l+r)>>1;
    CDQ(l,mid); CDQ(mid+1,r);
    sort(Q+l,Q+mid+1); sort(Q+mid+1,Q+r+1);
    int i=l,j=mid+1,pos=0;
    while (j<=r)
        {
            while (Q[i].opt==2 && i<=mid) i++;
            while (Q[j].opt==1 && j<=r) j++;
            if (i<=mid && Q[i].x<=Q[j].x) Modify(Q[i].y,Q[i].v),pos=i++;
                else if (j<=r) ans[Q[j].as]+=Query(Q[j].y)*Q[j].v,j++;
//          printf("%d %d\n",i,j);
        }
    for (int k=l; k<=pos; k++) if (Q[k].opt==1) Modify(Q[k].y,-Q[k].v);  
//  printf("end<%d %d>\n",l,r);
}
int main()
{
    N=read();
    int ID=0,as=0,opt;
    while (scanf("%d",&opt) && opt!=3)
        {
            ID++;
            if (opt==1) 
                {
                    int x=read(),y=read(),z=read();
                    Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x,Q[cnt].y=y,Q[cnt].v=z;
                    continue;
                }
            int x1=read(),y1=read(),x2=read(),y2=read();
            as++;
            Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x2,Q[cnt].y=y2,Q[cnt].v=+1,Q[cnt].as=as;
            Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x1-1,Q[cnt].y=y1-1,Q[cnt].v=+1,Q[cnt].as=as;
            Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x1-1,Q[cnt].y=y2,Q[cnt].v=-1,Q[cnt].as=as;
            Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x2,Q[cnt].y=y1-1,Q[cnt].v=-1,Q[cnt].as=as;
        }
//  for (int i=1; i<=cnt; i++) printf("%d  %d  %d  %d   %d\n",i,Q[i].opt,Q[i].x,Q[i].y,Q[i].v);
    CDQ(1,cnt);
    for (int i=1; i<=as; i++) printf("%d\n",ans[i]);
    return 0;
}

莫队算法  序列带修 树上不带修&带修

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define maxm 20010
#define maxc 1000100
int n,m,bll,ans[maxm],nl=1,nr=0,nt=0,an,pos[maxm],num[maxc],a[maxm],aa[maxm]; bool visit[maxc];
struct Asknode
{
    int l,r,t,id;
    bool operator < (const Asknode & A) const
        {
            if (pos[l]==pos[A.l] && pos[r]==pos[A.r]) return t<A.t;
                else if (pos[l]==pos[A.l]) return r<A.r;
                    else return l<A.l; 
        }
}q[maxm];int qn;
struct Changenode{int x,c,t,pre;}ch[maxm];int cn;
void move(int x)
{
    if (visit[x])
        {num[a[x]]--;if (num[a[x]]==0) an--; visit[x]=0;}
    else 
        {num[a[x]]++;if (num[a[x]]==1) an++; visit[x]=1;}
}
void movedown(int T)
{
    int x=ch[T].x,c=ch[T].c;
    if (visit[x])
        {num[a[x]]--; if (num[a[x]]==0) an--; a[x]=c; num[c]++; if (num[c]==1) an++;}
    else 
        a[x]=c;
}
void moveforward(int T)
{
    int x=ch[T].x,c=ch[T].pre;
    if (visit[x])
        {num[a[x]]--; if (num[a[x]]==0) an--; a[x]=c; num[c]++; if (num[c]==1) an++;}
    else
        a[x]=c;
}
void work(int x)
{
    int L=q[x].l,R=q[x].r,id=q[x].id,T=q[x].t;
    while (nl<L) move(nl),nl++;
    while (nl>L) nl--,move(nl);
    while (nr<R) nr++,move(nr);
    while (nr>R) move(nr),nr--;
    while (nt<T) nt++,movedown(nt);
    while (nt>T) moveforward(nt),nt--;
    ans[id]=an;
}
int main()
{
    n=read(),m=read(); bll=int(sqrt(n));
    for (int i=1; i<=n; i++) aa[i]=a[i]=read(),pos[i]=(i-1)/bll+1;
    for (int i=1; i<=m; i++)
        {
            char opt[5]; scanf("%s",opt); int x=read(),y=read();
            if (opt[0]=='Q')
                qn++,q[qn].id=qn,q[qn].l=x,q[qn].r=y,q[qn].t=cn;
            if (opt[0]=='R')
                cn++,ch[cn].t=i,ch[cn].x=x,ch[cn].c=y,ch[cn].pre=aa[x],aa[x]=y;
        }
    sort(q+1,q+qn+1);
    for (int i=1; i<=qn; i++) work(i);
    for (int i=1; i<=qn; i++) printf("%d\n",ans[i]);
    return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int read()
{
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x;
}
#define maxn 50100
#define maxq 100100
int n,m,fk,knum,ans,root; 
struct Edgenode{int to,next;}edge[maxn<<1];
int head[maxn],cnt=1;
void add(int u,int v)
{cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
void insert(int u,int v)
{add(u,v); add(v,u);}
int deep[maxn],father[maxn][25],dfsx,stack[maxn],top,rt[maxn],an[maxq],p[maxn];
struct Pointnode{int dfs,col;}po[maxn];
struct Asknode
{
    int a,b,u,v,id;
    bool operator < (const Asknode & A) const
        {
            if(rt[u]==rt[A.u]) return po[v].dfs<po[A.v].dfs;
                else return rt[u]<rt[A.u];
        }
}q[maxq];
bool visit[maxn];
int DFS(int now)
{
    int size=0;
    po[now].dfs=++dfsx;
    for (int i=1; i<=20; i++)
        if (deep[now]>=(1<<i))
            father[now][i]=father[father[now][i-1]][i-1];
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=father[now][0])
            {
                deep[edge[i].to]=deep[now]+1;
                father[edge[i].to][0]=now;
                size+=DFS(edge[i].to);  
                if (size>=fk)
                    {
                        knum++;
                        for(int j=1; j<=size; j++)
                            rt[stack[top--]]=knum;
                        size=0;
                    }   
            }
    stack[++top]=now;
    return size+1;
}   
int LCA(int x,int y)
{
    if (deep[x]<deep[y]) swap(x,y);
    int dd=deep[x]-deep[y];
    for (int i=0; i<=20; i++)
        if (dd&(1<<i) && dd>=(1<<i)) x=father[x][i];
    for (int i=20; i>=0; i--)
        if (father[x][i]!=father[y][i]) 
            x=father[x][i],y=father[y][i];
    if (x==y) return x; else return father[x][0];
}
void reserv(int x)
{
    if (!visit[x]) {visit[x]=1; p[po[x].col]++; if (p[po[x].col]==1) ans++;}
        else {visit[x]=0; p[po[x].col]--; if (p[po[x].col]==0) ans--;}
}
void work(int u,int v)
{
    while (u!=v)
        if (deep[u]>deep[v]) reserv(u),u=father[u][0];
            else reserv(v),v=father[v][0];
}
int main()
{
    n=read(),m=read(); fk=sqrt(n);
    for (int i=1; i<=n; i++) po[i].col=read();
    for (int u,v,i=1; i<=n; i++)
        {
            u=read(),v=read();
            if (!u) root=v;
                else if (!v) root=u;
                    else insert(u,v);
        }
    DFS(root);
    knum++; 
    while (top) rt[stack[top--]]=knum;
    for (int i=1; i<=m; i++) 
        {
            q[i].u=read();q[i].v=read();q[i].a=read();q[i].b=read();q[i].id=i;
            if (po[q[i].u].dfs>po[q[i].v].dfs) swap(q[i].u,q[i].v);
        }
    sort(q+1,q+m+1);
    int T=LCA(q[1].u,q[1].v);
    work(q[1].u,q[1].v); reserv(T); an[q[1].id]=ans;
    if (p[q[1].a] && p[q[1].b] && q[1].a!=q[1].b) an[q[1].id]--;
    reserv(T); 
    for (int i=2; i<=m; i++)
        {
            work(q[i-1].u,q[i].u);
            work(q[i-1].v,q[i].v);
            T=LCA(q[i].u,q[i].v);
            reserv(T); an[q[i].id]=ans;
            if(p[q[i].a] && p[q[i].b] && q[i].a!=q[i].b) an[q[i].id]--;
            reserv(T);
        }
    for (int i=1; i<=m; i++) printf("%d\n",an[i]);
    return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 100010
#define maxm 100010
#define maxq 100010
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,Q,fk,knum,rt[maxn];long long V[maxm],W[maxn],an[maxn],C[maxn],ans;
struct Edgenode{int to,next;}edge[maxn<<1];
int head[maxn],cnt;
void add(int u,int v)
{cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
void insert(int u,int v)
{add(u,v);add(v,u);}
int stack[maxn],top,dfsx,dfs[maxn],deep[maxn],father[maxn][25];
int DFS(int now)
{
    int size=0;
    dfs[now]=++dfsx;
    for (int i=1; i<=20; i++)
        if (deep[now]>=(1<<i)) father[now][i]=father[father[now][i-1]][i-1];
    for (int i=head[now]; i; i=edge[i].next)
        if (edge[i].to!=father[now][0])
            {
                deep[edge[i].to]=deep[now]+1;
                father[edge[i].to][0]=now;
                size+=DFS(edge[i].to);
                if (size>=fk)
                    {
                        knum++;
                        for (int j=1; j<=size; j++) rt[stack[top--]]=knum;
                        size=0;
                    }
            }
    stack[++top]=now;
    return size+1;            
}
int LCA(int x,int y)
{
    if (deep[x]<deep[y]) swap(x,y);
    int dd=deep[x]-deep[y];
    for (int i=0; i<=20; i++)
        if (dd&(1<<i) && dd>=(1<<i)) x=father[x][i];
    for (int i=20; i>=0; i--)
        if (father[x][i]!=father[y][i])
            x=father[x][i],y=father[y][i];
    if (x==y) return x; else return father[x][0];
}
bool visit[maxn]; int num[maxn];
void Reverse(int x)
{
    if (visit[x]) {visit[x]=0; ans-=W[num[C[x]]]*V[C[x]]; num[C[x]]--;}
        else {visit[x]=1;  num[C[x]]++; ans+=W[num[C[x]]]*V[C[x]];}    
//    printf("%d\n",ans);
}
void Change(int x,int y)
{
    if (visit[x]) Reverse(x),C[x]=y,Reverse(x); 
        else C[x]=y;
}
void work(int x,int y)
{
    while (x!=y)
        if (deep[x]>deep[y]) Reverse(x),x=father[x][0];
            else Reverse(y),y=father[y][0];
}
struct Asknode
{
    int a,b,t,id;
    bool operator < (const Asknode & A) const
        {
            if (rt[a]==rt[A.a] && rt[b]==rt[A.b]) return t<A.t;
                else if (rt[a]==rt[A.a]) return rt[b]<rt[A.b];
            return rt[a]<rt[A.a];
        }
}q[maxq];int numq;
struct Changenode{int a,b,t,p;}ch[maxq];int numc,p[maxq];
int main()
{
    n=read(),m=read(),Q=read(); fk=pow(n,2.0/3)*0.5;
    for (int i=1; i<=m; i++) V[i]=read();
    for (int i=1; i<=n; i++) W[i]=read();
    for (int u,v,i=1; i<=n-1; i++) u=read(),v=read(),insert(u,v);
    for (int i=1; i<=n; i++) C[i]=read();
    for (int i=1; i<=n; i++) p[i]=C[i];
    
    DFS(1); 
//    puts("OK");
//    for (int i=1; i<=n; i++) printf("%d %d %d %d\n",V[i],W[i],dfs[i],p[i]);
//    for (int i=1; i<=n; i++) printf("%d ",rt[i]); puts("");
//    puts("OK");
    while (top) rt[stack[top--]]=knum;    
    
    for (int i=1; i<=Q; i++)
        {
            int opt=read(),a=read(),b=read();
            if (opt) {if (dfs[a]>dfs[b]) swap(a,b); numq++;q[numq].a=a; q[numq].b=b; q[numq].t=numc; q[numq].id=numq;}
                else {numc++;ch[numc].a=a;ch[numc].b=b;ch[numc].t=i;ch[numc].p=p[a]; p[a]=b;}
        }
    sort(q+1,q+numq+1);
    //for (int i=1; i<=numq; i++) printf("%d %d %d %d\n",q[i].a,q[i].b,q[i].id,q[i].t);
    for (int i=1; i<=q[1].t; i++) Change(ch[i].a,ch[i].b);
    work(q[1].a,q[1].b);
    int T=LCA(q[1].a,q[1].b);
    Reverse(T); an[q[1].id]=ans; Reverse(T);
    for (int i=2; i<=numq; i++)
        {
            for(int j=q[i-1].t+1; j<=q[i].t; j++) Change(ch[j].a,ch[j].b);
            for(int j=q[i-1].t; j>q[i].t; j--) Change(ch[j].a,ch[j].p);
            work(q[i-1].a,q[i].a); work(q[i-1].b,q[i].b);
            T=LCA(q[i].a,q[i].b); Reverse(T); an[q[i].id]=ans; Reverse(T);
        }
    for (int i=1; i<=numq; i++) printf("%lld\n",an[i]);
    return 0;
}

  

posted @ 2017-01-07 20:02  DaD3zZ  阅读(187)  评论(0编辑  收藏  举报