• [模板]FJOI2017赛前整理


    图论

    KM

    时间复杂度:\(O(n^3)\).

    #define N 305
    int w[N][N],x[N],y[N]/*二分图左右两边的点的期望值*/,fr[N],sla[N],n;
    bool vx[N],vy[N]/*每个点每轮是否被尝试匹配过*/;
    inline bool match(int u){
    	int tmp;vx[u]=true;
    	for(int j=1;j<=n;++j){
    		if(vy[j]) continue;
    		tmp=x[u]+y[j]-w[u][j];
    		if(!tmp){//符合要求:两边期望值之和为权值
    			vy[j]=true;
    			if(!fr[j]||match(fr[j])){
    				fr[j]=u;return true;
    			}
    		} 
    		else sla[j]=min(sla[j],tmp);
    	} 
    	return false;
    }
    inline int KM(){
    	int tmp,ret=0;
    	for(int i=1;i<=n;++i){
    		x[i]=-INF;
    		for(int j=1;j<=n;++j)
    			x[i]=max(x[i],w[i][j]);
    	}
    	memset(y,0,sizeof(y)); 
    	memset(fr,0,sizeof(fr));
    	for(int i=1;i<=n;++i){//尝试为左侧每个点进行匹配
    		for(int j=1;j<=n;++j) sla[j]=INF;
    		while(true){
    			memset(vx,0,sizeof(vx));
    			memset(vy,0,sizeof(vy));
    			if(match(i)) break;
    			tmp=INF;
    			for(int j=1;j<=n;++j)
    				if(!vy[j]) tmp=min(tmp,sla[j]);
    			for(int j=1;j<=n;++j)
    				if(vx[j]) x[j]-=tmp;
    			for(int j=1;j<=n;++j)
    				if(vy[j]) y[j]+=tmp;
    				else sla[j]-=tmp; 
    		}
    	}
    	for(int i=1;i<=n;++i)
    		ret+=w[fr[i]][i];
    	return ret;
    }
    

    数据结构

    splay

    时间复杂度:\(O(nlogn)\).

    #define N 100005
    struct Splay{
    	int c[2],f,siz,val,cnt;//balabala...(根据题目需要的变量) 
    }tr[N];
    int n,rt,cnt;
    inline bool son(int u){
    	return tr[tr[u].f].c[1]==u;
    }
    inline void ins_p(int f,int u,int c){
    	tr[f].c[c]=u;tr[u].f=f;
    }
    inline void recnt(int u){
    	tr[u].siz=tr[tr[u].c[0]].siz+tr[tr[u].c[1]].siz+tr[u].cnt;
    }
    inline void rotate(int u){
    	int f=tr[u].f;bool c=son(u);
    	if(tr[f].f) ins_p(tr[f].f,u,son(f));
    	else tr[u].f=0,rt=u;
    	ins_p(f,tr[u].c[c^1],c);
    	ins_p(u,f,c^1);
    	recnt(f);recnt(u);
    }
    inline void splay(int u,int rt){
    	while(tr[u].f!=rt){
    		if(tr[tr[u].f].f==rt) rotate(u);
    		else if(son(tr[u].f)==son(u)){
    			rotate(tr[u].f);rotate(u);
    		}
    		else{
    			rotate(u);rotate(u);
    		}
    	}
    }
    inline int kth(int k)/*第k小的值*/{
    	int u=rt;
    	while(u){
    		if(k<=tr[tr[u].c[0]].siz)
    			u=tr[u].c[0];
    		else{
    			k-=tr[tr[u].c[0]].siz;
    			if(k<=tr[u].cnt) return tr[u].val;
    			k-=tr[u].cnt;u=tr[u].c[1];
    		}
    	}
    	return u;
    }
    inline int near(int u,bool c){
    	if(tr[u].c[c]){
    		u=tr[u].c[c];c^=1;
    		while(tr[u].c[c])
    			u=tr[u].c[c];
    		return u;
    	}
    	while(u&&son(u)==c) u=tr[u].f;
    	return tr[u].f;
    }
    inline int select(int u,int v){
    	u=near(u,0);v=near(v,1);
    	splay(u,0);splay(v,rt);
    	return tr[v].c[0];
    }
    inline void clear(int u){
    	tr[tr[u].f].c[son(u)]=0;
    	tr[u].c[0]=tr[u].c[1]=tr[u].f=0;
    	tr[u].siz=tr[u].val=tr[u].cnt=0;
    }
    inline void del(int u,int v){
    	u=select(u,v);
    	int f=tr[u].f;clear(u);u=f;
    	while(u){
    		recnt(u);u=tr[u].f;
    	}
    }
    inline int find(int k){
    	int u=rt;
    	while(u&&tr[u].val!=k)
    		u=tr[u].c[k>tr[u].val];
    	return u;
    }
    inline void insert(int k){
    	int u=find(k);
    	if(u){
    		++tr[u].cnt;
    		while(u){
    			recnt(u);u=tr[u].f;
    		}
    		return;
    	}
    	u=rt;
    	while(tr[u].c[k>tr[u].val])
    		u=tr[u].c[k>tr[u].val];
    	tr[++cnt].val=k;
    	tr[cnt].siz=tr[cnt].cnt=1;
    	if(!u){
    		rt=cnt;recnt(rt);return;
    	}
    	ins_p(u,cnt,k>tr[u].val);
    	splay(cnt,0);
    }
    

    LCT

    时间复杂度:\(O(nlogn)\).

    #define N 100005
    struct LCT{
    	int c[2],f,rev;
    }tr[N];
    int n;
    stack<int> s;
    inline void down(int u){
    	if(tr[u].rev){
    		tr[u].rev=0;
    		tr[tr[u].c[0]].rev^=1;
    		tr[tr[u].c[1]].rev^=1;
    		swap(tr[u].c[0],tr[u].c[1]);
    	}
    }
    inline bool son(int u){
    	return tr[tr[u].f].c[1]==u;
    }
    inline void ins_p(int f,int u,int c){
    	tr[f].c[c]=u;tr[u].f=f;
    }
    inline bool isroot(int u){
    	return tr[tr[u].f].c[0]!=u&&tr[tr[u].f].c[1]!=u;
    }
    inline void recnt(int u){
    	//balabala...
    }
    inline void rotate(int u){
    	int f=tr[u].f;bool c=son(u);
    	if(isroot(f)) tr[u].f=tr[f].f;
    	else ins_p(tr[f].f,u,son(f));
    	ins_p(f,tr[u].c[c^1],c);
    	ins_p(u,f,c^1);
    	recnt(f);recnt(u);
    }
    inline void splay(int u){
    	s.push(u);
    	for(int v=u;!isroot(v);v=tr[v].f) s.push(tr[v].f);
    	while(!s.empty()){
    		down(s.top());s.pop();
    	}
    	while(!isroot(u)){
    		if(isroot(tr[u].f)) rotate(u);
    		else if(son(tr[u].f)==son(u)){
    			rotate(tr[u].f);rotate(u);
    		}
    		else{
    			rotate(u);rotate(u);
    		}
    	}
    }
    inline void access(int u){
    	for(int lst=0;u;lst=u,u=tr[u].f){
    		splay(u);tr[u].c[1]=lst;recnt(u);
    	}
    }
    inline void makeroot(int u){
    	access(u);splay(u);tr[u].rev^=1;
    }
    inline int findroot(int u){
    	access(u);splay(u);
    	while(down(u),tr[u].c[0]) u=tr[u].c[0];
    	splay(u);
    	return u;
    } 
    inline void select(int u,int v){
    	makeroot(u);access(v);splay(v);//u为v的左孩子 
    }
    inline void link(int u,int v){
    	makeroot(u);tr[u].f=v; 
    }
    inline void cut(int u,int v){
    	select(u,v);tr[v].c[0]=tr[u].f=0;recnt(v); 
    }
    

    Dsu on tree

    时间复杂度:\(O(nlogn)\).

    #define N 100005
    struct graph{
    	int nxt,to;
    }e[N<<1]; 
    int g[N],w[N],t[N],fa[N],son[N],ans[N];
    bool big[N];
    inline void add(int u,int del){
    	++t[w[u]];
    	if(del>0) ;//有可能更新答案 
    	if(del<0) ;//有可能返回历史版本
    	for(int i=g[u];i;i=e[i].nxt)
    		if(e[i].to!=fa[u]&&!big[e[i].to])
    			add(e[i].to,del);
    } 
    inline void dsu(int u,bool kep){
    	for(int i=g[u];i;i=e[i].nxt)
    		if(e[i].to!=fa[u]&&e[i].to!=son[u])
    			dsu(e[i].to,false);
    	if(son[u]){
    		dsu(son[u],true);big[son[u]]=true;
    	}
    	add(u,1);
    	ans[u]=/*当前答案*/;
    	if(son[u]) big[son[u]]=false;
    	if(!kep){
    		add(u,-1);//清除数据,返回历史版本
    	}
    }
    

    计算几何

    struct point{
        int x,y;
    };
    point operator - (point a,point b){
        return (point){a.x-b.x,a.y-b.y};
    }
    ll operator * (point a,point b){
        return 1ll*a.x*b.y-1ll*b.x*a.y;
    }
    

    凸包

    时间复杂度:\(O(nlogn)\).

    #define N 100005
    #define eps 1e-13
    bool operator < (point a,point b){
        if(a.x!=b.x) return a.x<b.x;
        return a.y<b.y;
    }
    inline double sqr(int k){
        return (double)(k*k);
    }
    inline double dis(point x,point y){
        return sqr(x.x-y.x)+sqr(x.y-y.y);
    }
    inline bool cmp(point x,point y){
        if(fabs(x.an-y.an)<eps)
            return dis(x,a[1])>dis(y,a[1]); 
        return x.an<y.an;
    }
    inline void convex(point a[],int &n){
        for(int i=2;i<=n;++i)
            if(a[i]<a[1]) swap(a[i],a[1]);
        for(int i=2;i<=n;++i)
            a[i].an=atan2(a[i].y-a[1].y,a[i].x-a[1].x);
        sort(a+2,a+1+n,cmp);
        int m=1;a[++n]=a[1];
        for(int i=2;i<=n;++i){
            if(fabs(a[i].an-a[i-1].an)<eps) continue;
            while(m>1&&(a[i]-a[m-1])*(a[m]-a[m-1])>0) --m;
            a[++m]=a[i];
        }
        n=m;
    } 
    

    旋转卡壳

    时间复杂度:\(O(n)\).

    #define N 100005
    point a[N];int n;
    inline double sqr(int k){
        return (double)(k*k);
    }
    inline double dis(point x){
        return sqrt(sqr(x.x)+sqr(x.y));
    }
    inline int Nxt(int k){
        return (++k>n)?1:k;
    }
    inline double rotate(){
        point p;double di,dia=0.0;
        if(n==1) return dia;
        for(int i=1,j=2;i<=n;++i){
            p=a[Nxt(i)]-a[i];
            while(abs(p*(a[j]-a[i]))<abs(p*(a[Nxt(j)]-a[i]))) j=Nxt(j);
            dia=max(dia,max(dis(a[i]-a[j]),dis(a[Nxt(i)]-a[Nxt(j)])));
        }
        return dia;
    }
    

    转角法

    时间复杂度:\(O(n)\).

    point a[N];int n;
    inline int cmp(ll x){
        return x?(x>0?1:-1):0;
    }
    inline bool onseg(point p,point a,point b){
        if(cmp((a-p)*(b-p))) return false;
        return cmp(a.x-p.x)*cmp(b.x-p.x)<=0&&cmp(a.y-p.y)*cmp(b.y-p.y)<=0;
    }
    inline int chk(point p){
        int cnt=0,d1,d2,k;
        for(int i=1;i<=n;++i){
            if(onseg(p,a[i],a[i+1]) return -1;
            k=cmp((a[i+1]-a[i])*(p-a[i]));
            d1=cmp(a[i].y-p.y);d2=cmp(a[i+1].y-p.y);
            if(k>0&&d1<=0&&d2>0) ++cnt;
            if(k<0&&d2<=0&&d1>0) --cnt;
        }
        return cnt?1:0;
    }
    

    平面最近点对

    时间复杂度:\(O(nlogn)\).

    point a[N];int n;
    bool cmpx(point a,point b){
        if(a.x!=b.x) return a.x<b.x;
        return a.y<b.y;
    }
    bool cmpy(point a,point b){
        if(a.y!=b.y) return a.y<b.y;
        return a.x<b.x;
    }
    inline double sqr(int k){
        return (double)(k*k);
    }
    inline double dis(point a,point b){
        return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
    }
    inline double md(int l,int r){
        double ret=INF;
        if(r-l<=20){
            for(int i=l;i<r;++i)
                for(int j=i+1;j<=r;++j)
                    ret=min(ret,dis(a[i],a[j]));
            return ret;
        }
        int mid=(l+r)>>1;
        ret=min(md(l,mid),md(mid+1,r));
        while(a[l].x+ret<a[mid].x) ++l;
        while(a[r].x-ret>a[mid].x) --r;
        sort(a+l,a+r+1,cmpy);
        for(int i=l;i<=r;++i)
            for(int j=min(i+6,r);j>i;--j)
                ret=min(ret,dis(a[i],a[j]));
        sort(a+l,a+r+1,cmpx);
        return ret;
    }
    inline double middis(){
        sort(a+1,a+1+n,cmpx);
        return md(1,n);
    }
    

    半平面交

    \(f(x)=Ax+By+C.\\Ax+By+C\geq{0}:(-1,f(-1))->(1,f(1));\\Ax+By+C\leq{0}:(1,f(1))->(-1,f(-1)).\)

    struct line{
        point s,t;double an;
    }a[N],q[N];
    int h,t,n;
    inline bool cmp(line a,line b){
        if(fabs(a.an-b.an)>eps) return a.an<y.an;
        return (a.t-a.s)*(b.s-a.s)>0;
    }
    inline point inter(line a,line b){
        double s1,s2,tmp;point ret;
        s1=(b.t-a.s)*(a.t-a.s);
        s2(a.t-a.s)*(b.s-a.s);
        tmp=s2/(s1+s2);
        ret.x=b.s.x+(b.t.x-b.s.x)*tmp;
        ret.y=b.s.y+(b.t.y-b.s.y)*tmp;
        return ret;
    }
    inline bool chk(point p,line l){
        return (p-l.s)*(l.t-l.s)>0;
    }
    inline void hpi(){
        int m=1;
        for(int i=1;i<=n;++i)
            a[i].an=atan2(a[i].t.y-a[i].s.y,a[i].t.x-a[i].s.x);
        sort(a+1,a+1+n,cmp);
        for(int i=2;i<=n;++i)
            if(fabs(a[i].an-a[i-1].an)>eps) a[++m]=a[i];
        h=1;t=0;
        for(int i=1;i<=m;++i){
            while(h<t&&chk(inter(q[t],q[t-1]),a[i]) --t;
            while(h<t&&chk(inter(q[h],q[h+1]),a[i]) ++h;
            q[++t]=a[i];
        }
        while(h<t&&chk(inter(q[t],q[t-1]),q[h]) --t;
        while(h<t&&chk(inter(q[h],q[h+1]),q[t]) ++h;
        return t-h+1>=3;
    }
    

    数论

    FFT

    时间复杂度:\(O(nlogn)\).

    #define N 100005
    typedef long long ld;
    const ld pi=acos(-1.0);
    struct cp{
    	ld x,y;
    	cp() {}
    	cp(ld x,ld y):x(x),y(y) {}
    	friend cp operator + (cp a,cp b){
    		return cp(a.x+b.x,a.y+b.y); 
    	}
    	friend cp operator - (cp a,cp b){
    		return cp(a.x-b.x,a.y-b.y);
    	}
    	friend cp operator * (cp a,cp b){
    		return cp(a.x*b.x-a.y*b.y,a.y*b.x+a.x*b.y);
    	}
    }a[N],b[N],c[N];
    namespace FFT{
    	const int F=1e5+10;
    	cp w[2][F];int re[F],n;
    	inline void init(int k){
    		k<<=1;n=1;while(n<k) n<<=1;
    		for(int i=0;i<n;++i){
    			w[0][i]=cp(cos(pi*2/n*i),sin(pi*2/n*i));
    			w[1][i]=cp(w[0][i].x,-w[0][i].y);
    		}
    		k=0;while((1<<k)<n) ++k;
    		for(int i=0,t;i<n;++i){
    			t=0;
    			for(int j=0;j<k;++j)
    				if(i&(1<<j)) t|=(1<<k-j-1);
    			re[i]=t;
    		}
    	}
    	inline void DFT(cp *a,int ty){
    		cp *o=w[ty];
    		for(int i=0;i<n;++i)
    			if(i<re[i]) swap(a[i],a[re[i]]);
    		cp tmp;
    		for(int l=2,m;l<=n;l<<=1){
    			m=l>>1;
    			for(cp *p=a;p!=a+n;p+=l){
    				for(int i=0;i<m;++i){
    					tmp=o[n/l*i]*p[i+m];
    					p[i+m]=p[i]-tmp;p[i]=p[i]+tmp;
    				}	
    			}
    		}
    		if(ty) for(int i=0;i<n;++i)
    			a[i].x/=(ld)(n),a[i].y/=(ld)(n);
    	}
    }
    inline void Aireen(){
    	FFT::DFT(a,0);FFT::DFT(b,0);
    	for(int i=0;i<FFT::n;++i)
    		c[i]=a[i]*b[i];
    	FFT::DFT(c,1);
    }
    

    高斯消元

    时间复杂度:\(O(n^3)\).

    #define N 101
    #define eps 1e-13
    double a[N][N],ans[N];
    int n;bool b[N];
    inline void gauss(int n){
    	int m=0;double tmp;
    	memset(b,0,sizeof(b));
    	for(int i=0;i<n;++i){
    		for(int j=m;j<n;++j){
    			if(fabs(a[j][i])>eps){
    				for(int k=i;k<=n;++k)
    					swap(a[m][k],a[j][k]);
    				break; 
    			}
    		}
    		if(fabs(a[m][i])<eps) continue;
    		for(int j=0;j<n;++j)
    			if(j!=m&&fabs(a[j][i])>eps){
    				tmp=a[j][i]/a[m][i];
    				for(int k=i;k<=n;++k)
    					a[j][k]-=tmp*a[m][k];
    			}
    		b[i]=true;++m;
    	}
    	for(int i=0;i<n;++i)
    		if(b[i]) for(int j=0;j<n;++j)
    			if(fabs(a[j][i])>eps){
    				ans[i]=a[j][n]/a[j][i];break;
    			}
    }
    

    字符串

    SA

    时间复杂度:\(O(nlogn)\).

    #define N 100005
    int a[N],sa[N],rk[N],ht[N],fir[N],sec[N],bu1[N],bu2[N],tmp[N],n;
    inline void getSA(){
    	memset(bu1,0,sizeof(bu1));
    	for(int i=1;i<=n;++i) ++bu1[a[i]];
    	for(int i=1;i<=n;++i) bu1[i]+=bu1[i-1];
    	for(int i=n;i;--i) sa[bu1[a[i]]--]=i;
    	rk[sa[1]]=1;
    	for(int i=2;i<=n;++i){
    		rk[sa[i]]=rk[sa[i-1]];
    		if(a[sa[i]]!=a[sa[i-1]]) ++rk[sa[i]];
    	}
    	for(int t=1;rk[sa[n]]<n;t<<=1){
    		memset(bu1,0,sizeof(bu1));
    		memset(bu2,0,sizeof(bu2));
    		for(int i=1;i<=n;++i){
    			++bu1[fir[i]=rk[i]];
    			++bu2[sec[i]=((i+t>n)?0:rk[i+t])];
    		}
    		for(int i=1;i<=n;++i) bu2[i]+=bu2[i-1];
    		for(int i=n;i;--i) tmp[bu2[sec[i]]--]=i;
    		for(int i=1;i<=n;++i) bu1[i]+=bu1[i-1];
    		for(int i=n;i;--i) sa[bu1[fir[tmp[i]]]--]=tmp[i];
    		rk[sa[1]]=1;
    		for(int i=2;i<=n;++i){
    			rk[sa[i]]=rk[sa[i-1]];
    			if(fir[sa[i]]!=fir[sa[i-1]]||sec[sa[i]]!=sec[sa[i-1]]) ++rk[sa[i]];
    		}
    	}
    	for(int i=1,j,k=0;i<=n;++i){
    		if(k) --k;
    		j=sa[rk[i]-1];
    		while(j+k<=n&&i+k<=n&&a[j+k]==a[i+k]) ++k;
    		ht[rk[i]]=k;
    	}
    }
    

    2017-04-21 11:38:49

  • 相关阅读:
    Z-stack之OSAL初始化流程
    回调函数
    VCC,VDD,VEE,VSS,VPP 表示的意义
    ARM内核全解析,从ARM7,ARM9到Cortex-A7,A8,A9,A12,A15到Cortex-A53,A57
    SQL Server 2005 版本的操作系统兼容性详细列表
    Windows Xp Home Edition 安装IIS组件
    MySql 5.7中添加用户,新建数据库,用户授权,删除用户,修改密码
    AtCoder Beginner Contest 077(ABC)
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)(A B C D)
    B. Which floor?
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15602576.html
Copyright © 2020-2023  润新知