zoukankan      html  css  js  c++  java
  • [OI]省选前模板整理

    省选前把板子整理一遍,如果发现有脑抽写错的情况,欢迎各位神犇打脸 :)

    数学知识

    数论:

    //组合数
    //C(n,m) 在n个数中选m个的方案数 
    ll C[N][N];
    void get_C(int n)
    {
    	for(int i=1;i<=n;i++) 
    	{
    		C[i][i]=C[i][0]=1;
    		for(int j=1;j<i;j++)
    			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    	}
    }
    //欧几里得算法
    //(a,b) 
    ll gcd(ll a,ll b)
    {
    	return b==0? a:gcd(b,a%b);
    }
    //拓展欧几里得算法
    //解同余方程 a*x+b*y = (a,b) 
    ll exgcd(ll a,ll b,ll& d,ll& x,ll& y)
    {
    	if(!b) { d=a; x=1; y=0; }
    	else { exgcd(b,a%b,d,y,x); y-=x*(a/b); }
    }
    //逆元 
    //a*inv(a,n) = 1 mod n
    ll inv(ll a,ll n)
    {
    	ll d,x,y;
    	exgcd(a,n,d,x,y);
    	return d==1? (x+n)%n:-1;
    }
    //lucas定理
    //计算较大,有模数的组合数 
    ll fac[N];
    void get_pre(int n)
    {
    	for(int i=1;i<=n;i++) 
    		fac[i]=(fac[i-1]*i)%mod;
    }
    ll C(ll n,ll m,ll mod)
    {
    	if(n<m) return 0;
    	if(n<mod&&m<mod) 
    		return fac[n]*inv(fac[m],mod)%mod*inv(fac[n-m],mod)%mod;
    	return C(n/mod,m/mod,mod)*C(n%mod,m%mod,mod)%mod;
    }
    //快速幂
    //a^p % mod 
    ll pow(ll a,ll p,ll mod)
    {
    	ll ans=1;
    	while(p) 
    	{
    		if(p&1) ans=(ans*a)%mod;
    		a=(a*a)%mod; p>>=1;
    	}
    	return ans;
    }
    //中国剩余定理
    //解线性同余方程组 
    //sigma{ ai*(1-ai*mi) } % M  , ai*mi+wi*y=1
    ll a[N],m[N];
    ll china(int n)
    {
    	ll M=1,d,x=0,y;
    	for(int i=1;i<=n;i++) M*=m[i];
    	for(int i=1;i<=n;i++)
    	{
    		ll w=M/m[i];
    		exgcd(m[i],w,d,d,y);
    		x=(x+y*w*a[i])%M;
    	}
    	return (x+M)%M;
    }
    //大步小步算法
    //计算a^x=b mod n中的最小x
    map<int,int> mp;
    int BSGS(int a,int b,int n)
    {
    	int m=sqrt(n)+1,e=1,i;
    	int v=inv(pow(a,m,n),n);
    	mp[e]=0;
    	for(i=1;i<m;i++)
    	{
    		e=(e*m)%n;
    		if(!mp.count(e)) mp[e]=i;
    	}
    	for(i=0;i<m;i++)
    	{
    		if(mp.count(b)) return i*m+mp[b];
    		b=(b*v)%mod;
    	}
    	return -1;
    }
    //快速筛法求素数表
    int su[N],vis[N];
    void get_su(int n)
    {
    	for(int i=2;i<=n;i++)
    	{
    		if(!vis[i]) su[++su[0]]=i;
    		for(int j=1;j<=su[0]&&i*su[j]<=n;j++)
    		{
    			vis[i*su[j]]=1;
    			if(i%su[j]==0) break;
    		}
    	}
    }
    //欧拉函数
    //phi(n)小于n的数中与n互素的数的个数 
    ll get_phi(int n)
    {
    	int m=sqrt(n)+1;
    	ll ans=n;
    	for(int 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;
    }
    ll phi[N];
    void get_phi_table(int n)
    {
    	phi[1]=1;
    	for(int i=2;i<=n;i++) if(!phi[i])
    	{
    		for(int j=i;j<=n;j+=i) 
    		{
    			if(!phi[j]) phi[j]=j;
    			phi[j]=phi[j]/i*(i-1);
    		}
    	}
    }
    //莫比乌斯函数 int mu[N],su[N],vis[N]; void get_mu(int n) { mu[1]=1; for(int i=2;i<=n;i++) { if(!vis[i]) mu[i]=-1,su[++su[0]]=i; for(int j=1;j<=su[0]&&i*su[j]<=n;j++) { vis[i*su[j]]=1; if(i%su[j]==0) mu[i*su[j]]=0; else mu[i*su[j]]=-mu[i]; } } } //高斯消元 //解线性方程组 double a[N][N]; void gause(int n) { for(int i=1;i<=n;i++) { int r=i; for(int j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[r][i])) r=i; for(int j=1;j<=n+1;j++) swap(a[i][j],a[r][j]); for(int j=n+1;j>=i;j--) for(int k=i+1;k<=n;k++) a[k][j]-=a[k][i]/a[i][i]*a[i][j]; } for(int i=n;i;i--) { for(int j=i+1;j<=n;j++) a[i][n+1]-=a[j][n+1]*a[i][j]; a[i][n+1]/=a[i][i]; } }

    高精度:

    int trans(char* s,int st,int ed)
    {
        int x=0;
        for(int i=st;i<ed;i++) x=x*10+s[i]-'0';
        return x;
    }
    
    struct Bign
    {
        int len; ll N[maxn];
        Bign() { len=0; memset(N,0,sizeof(N)); }
        Bign(ll num) {  *this=num; }
        Bign(const char* s) { *this=s; }
        void print()
        {
            printf("%d",N[len-1]);
            for(int i=len-2;i>=0;i--)
                printf("%08d",N[i]);
            puts("");
        }
        Bign operator = (const ll x)
        {
            ll num=x;
            while(num>base)
            {
                N[len++]=num%base;
                num/=base;
            }
            if(num) N[len++]=num;
            return *this;
        }
        Bign operator = (char* s)
        {
            int L=strlen(s);
            len=(L-1)/wlen+1;
            for(int i=0;i<len;i++)
            {
                int ed=L-i*wlen;
                int st=max(0,ed-wlen);
                N[i]=trans(s,st,ed);
            }
            return *this;
        }
        bool operator < (const Bign& B) const
        {
            if(len!=B.len) return len<B.len;
            for(int i=len-1;i>=0;i--)
                if(N[i]!=B.N[i]) return N[i]<B.N[i];
            return 0;
        }
        bool operator <= (const Bign& B) const
        {
            return !(B<(*this));
        }
         
        void clear()
        {
            while(len>1&&N[len-1]==0) len--;
        }
         
        Bign operator + (const Bign& B) const
        {
            Bign C;
            C.len=max(len,B.len)+10;
            for(int i=0;i<C.len;i++)
            {
                C.N[i]+=N[i]+B.N[i];
                C.N[i+1]+=C.N[i]/base;
                C.N[i]%=base;
            }
            C.clear();
            return C;
        }
        Bign operator - (Bign B)
        {
            Bign C=*this;
            C.len=max(C.len,B.len);
            for(int i=0;i<C.len;i++)
            {
                if(C.N[i]<B.N[i]) C.N[i+1]--,C.N[i]+=base;
                C.N[i]=C.N[i]-B.N[i];
            }
            C.clear();
            return C;
        }
        Bign operator * (const Bign& B) const
        {
            Bign C;
            C.len=len+B.len;
            for(int i=0;i<len;i++)
                for(int j=0;j<B.len;j++)
                    C.N[i+j]+=N[i]*B.N[j];
            for(int i=0;i<C.len;i++)
            {
                C.N[i+1]+=C.N[i]/base;
                C.N[i]%=base;
            }
            C.clear();
            return C;
        }
        Bign operator / (const Bign& B)
        {
            Bign C,F;
            C.len=len;
            for(int i=len-1;i>=0;i--)
            {
                F=F*base;
                F.N[0]=N[i];
                while(B<=F)
                {
                    F=F-B;
                    C.N[i]++;
                }
            }
            C.clear();
            return C;
        }
        Bign operator % (const Bign& B)
        {
            Bign r=*this/B;
            return *this-r*B;
        }
     
    }A,B;
    

      

    矩阵乘法:

    //矩阵乘法 
    struct Mat 
    {
    	int r,c; ll N[maxn][maxn];
    	Mat(int r=0,int c=0) 
    	{
    		this->r=r,this->c=c;
    		memset(N,0,sizeof(N));
    	}
    	Mat operator * (const Mat& B) const
    	{
    		Mat C(r,B.c);
    		for(int i=0;i<r;i++)
    			for(int j=0;j<B.c;j++)
    				for(int k=0;k<c;k++)
    					C.N[i][j]=(C.N[i][j]+N[i][k]*B.N[k][j])%mod;
    		return C;
    	}
    	Mat operator ^ (int p)
    	{
    		Mat ans(r,r),tmp=*this;
    		for(int i=0;i<r;i++) ans.N[i][i]=1;
    		while(p)
    		{
    			if(p&1) ans=ans*tmp;
    			tmp=tmp*tmp; p>>=1;
    		}
    		return ans;
    	}
    	
    }; 
    

     

    数据结构

    树状数组:

    //树状数组
    int C[N],mx;
    void Add(int x,int v)
    {
        for(int i=x;i<=mx;i+=i&-i) C[i]+=v;
    }
    int query(int x)
    {
        int ans=0;
        for(int i=x;i;i-=i&-i) ans+=C[i];
        return ans;
    }
    

      

    线段树:

    //线段树
    //区间加,区间乘,区间求和 
    int mod;
    struct Tnode 
    {
    	int u,l,r;
    	ll sum,add,mul;
    	void mulv(ll x) {
    		sum=(sum*x)%mod;
    		mul=(mul*x)%mod;
    		add=(add*x)%mod;
    	}
    	void addv(ll x) {
    		sum=(sum+(r-l+1)*x%mod)%mod;
    		add=(add+x)%mod;
    	}
    	void pushdown() ;
    	void maintain() ;
    }T[N];
    void Tnode::pushdown() {
    	if(mul^1) {
    		T[u<<1].mulv(mul);
    		T[u<<1|1].mulv(mul);
    		mul=1;
    	}
    	if(add) {
    		T[u<<1].addv(add);
    		T[u<<1|1].addv(add);
    		add=0;
    	}
    }
    void Tnode::maintain() {
    	sum=(T[u<<1].sum+T[u<<1|1].sum)%mod;
    }
    
    void update(int u,int L,int R,int x,int f)
    {
    	T[u].pushdown();
    	if(L<=T[u].l&&T[u].r<=R) {
    		if(!f) T[u].addv(x);
    		else T[u].mulv(x);
    	} else {
    		int mid=T[u].l+T[u].r>>1;
    		if(L<=mid) update(u<<1,L,R,x,f);
    		if(mid<R) update(u<<1|1,L,R,x,f);
    		T[u].maintain();
    	}
    }
    ll query(int u,int L,int R)
    {
    	T[u].pushdown();
    	if(L<=T[u].l&&T[u].r<=R)
    		return T[u].sum;
    	else {
    		int mid=T[u].l+T[u].r>>1;
    		ll ans=0;
    		if(L<=mid) ans=(ans+query(u<<1,L,R))%mod;
    		if(mid<R) ans=(ans+query(u<<1|1,L,R))%mod;
    		return ans; 
    	}
    }
    ll a[N];
    
    void build(int u,int l,int r)
    {
    	T[u]=(Tnode){ u,l,r,0,0,1 };
    	if(l==r) {
    		T[u].sum=a[l];
    	} else {
    		int mid=l+r>>1;
    		build(u<<1,l,mid);
    		build(u<<1|1,mid+1,r);
    		T[u].maintain();
    	}
    }
    

    Treap:

    //Treap 
    struct Node 
    {
    	Node *ch[2];
    	int v,r,m,w,s;
    	Node(int v):v(v) { ch[0]=ch[1]=NULL; r=rand(); s=w=1; }
    	int cmp(int x) {
    		if(v==x) return -1;
    		return x<v? 0:1;
    	}
    	void maintain() {
    		s=w;
    		if(ch[0]!=NULL) s+=ch[0]->s;
    		if(ch[1]!=NULL) s+=ch[1]->s;
    	}
    };
    
    void rotate(Node* &o,int d)
    {
    	Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    	o->maintain(); k->maintain(); o=k;
    }
    void insert(Node *&o,int x)
    {
    	if(o==NULL) o=new Node(x);
    	int d=o->cmp(x);
    	if(d==-1) o->w++;
    	else {
    		insert(o->ch[d],x);
    		if(o->ch[d]->r > o->r) rotate(o,d^1);
    	}
    	o->maintain();
    }
    void remove(Node *&o,int x)
    {
    	int d=o->cmp(x);
    	if(d==-1) 
    	{
    		if(o->s>1) { o->w--; o->maintain(); return ; }
    		else {
    			if(o->ch[0]!=NULL&&o->ch[1]!=NULL) {
    				int d2=o->ch[0]->r > o->ch[1]->r ? 1:0;
    				rotate(o,d2); remove(o->ch[d2],x);
    			} else {
    				if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1];
    				delete o;
    			}
    		}
    	} else 
    		remove(o->ch[d],x);
    	if(o!=NULL) o->maintain();
    }
    int kth(Node* o,int rk)
    {
    	if(o==NULL) return 0;
    	int s=o->ch[0]==NULL? 0:o->ch[0]->s;
    	if(rk==s+1) return o->v;
    	else if(rk<=s) return kth(o->ch[0],rk);
    	else return kth(o->ch[1],rk-s-o->w);
    }
    int rank(Node* o,int x)
    {
    	if(o==NULL) return 0;
    	int s=o->ch[0]==NULL? 0:o->ch[0]->s;
    	int d=o->cmp(x);
    	if(d==-1) return 1;
    	else if(d==0) return rank(o->ch[0],x);
    	else return s+o->w+rank(o->ch[1],x);
    }
    int tmp;
    void before(Node* o,int x)
    {
    	if(o==NULL) return ;
    	if(o->v<x) { tmp=max(tmp,o->v); before(o->ch[1],x); }
    	else before(o->ch[0],x);
    }
    void after(Node* o,int x)
    {
    	if(o==NULL) return ;
    	if(o->v>x) { tmp=min(tmp,o->v); after(o->ch[0],x); }
    	else after(o->ch[1],x);
    }
    

    splay:

    //splay自上而下 
    struct Node 
    {
    	Node *ch[2];
    	int s;
    	int cmp(int x)
    	{
    		int d=x-ch[0]->s;
    		if(d==1) return -1;
    		return d<=0? 0:1;
    	}
    	void maintain()
    	{
    		s=ch[0]->s+ch[1]->s;
    	}
    	void pushdown() {}
    }mempool[N],*G=mempool;
    
    Node* null=new Node();
    void rotate(Node* &o,int d)
    {
    	Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d],k->ch[d]=o;
    	o->maintain(); k->maintain(); o=k;
    }
    void splay(Node* &o,int k)
    {
    	o->pushdown();
    	int d=o->cmp(k);
    	if(d==1) k-=o->ch[0]->s+1;
    	if(d!=-1) {
    		Node* p=o->ch[d];
    		p->pushdown();
    		int d2=p->cmp(k),k2=d2==0? k:k-p->ch[d]->s-1;
    		if(d2!=-1) {
    			splay(p->ch[d2],k2);
    			if(d==d2) rotate(o,d^1); else rotate(o->ch[d],d);
    		}
    		rotate(o,d^1);
    	}
    }
    Node* merge(Node* left,Node* right)
    {
    	splay(left,left->s);
    	left->ch[1]=right,left->maintain();
    	return left;
    }
    void split(Node* o,int k,Node*&left,Node*&right)
    {
    	splay(o,k);
    	left=o,right=left->ch[1],left->ch[1]=NULL;
    	left->maintain();
    }
    Node* build(int l,int r)
    {
    	if(r<l) return null;
    	int mid=l+r>>1;
    	G->s=1;
    	G->ch[0]=build(l,mid-1);
    	G->ch[1]=build(mid+1,r);
    	G->maintain();
    	return G++;
    }
    

    主席树:

    //主席树 
    struct Tnode 
    {
    	Tnode *ls,*rs;
    	int sum;
    } *T[N*50],mempool[N*50],*G=mempool;
    
    Tnode* Nw(Tnode* l,Tnode* r,int x)
    {
    	G->ls=l,G->rs=r,G->sum=x;
    	return G++;
    }
    Tnode* build(Tnode* p,int l,int r,int pos)
    {
    	if(l==r) 
    		return Nw(T[0],T[0],p->sum+1);
    	else {
    		int mid=l+r>>1;
    		if(pos<=mid) return Nw(build(p->ls,l,mid,pos),p->rs,p->sum+1);
    		else return Nw(p->ls,build(p->rs,mid+1,r,pos),p->sum+1);
    	}
    }
    int query(Tnode* x,int l,int r,int pos)
    {
    	if(l==r) return x->sum;
    	else {
    		int mid=l+r>>1;
    		if(pos<=mid) return query(x->ls,l,mid,pos);
    		else return query(x->rs,mid+1,r,pos);
    	}
    }
    

    Link-Cut-Tree

    //Link-Cut-Tree 
    namespace LCT 
    {
    
    	struct Node {
    		Node *ch[2],*fa;
    		int rev;
    		//others v
    		Node() {};
    		Node(int x) ; 
    		void reverse() {
    			swap(ch[0],ch[1]);
    			rev^=1;
    		}
    		void up_push() {
    			if(fa->ch[0]==this||fa->ch[1]==this)
    				fa->up_push();
    			if(rev) {
    				ch[0]->reverse();
    				ch[1]->reverse();
    				rev=0;
    			}
    		}
    		void maintain() { }
    	} T[N<<1],*null=&T[0];
    	Node::Node(int x) {
    		ch[0]=ch[1]=fa=null;
    		rev=0; //v=x;
    	}
    	void rot(Node* o,int d) {
    		Node* p=o->fa;
    		p->ch[d]=o->ch[d^1];
    		o->ch[d^1]->fa=p;
    		o->ch[d^1]=p;
    		o->fa=p->fa;
    		if(p==p->fa->ch[0])
    			p->fa->ch[0]=o;
    		else if(p==p->fa->ch[1])
    			p->fa->ch[1]=o;
    		p->fa=o;
    		p->maintain();
    	}
    	void splay(Node* o) {
    		o->up_push();
    		Node *nf,*nff;
    		while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
    			nf=o->fa,nff=nf->fa;
    			if(o==nf->ch[0]) {
    				if(nf==nff->ch[0]) rot(nf,0);
    				rot(o,0);
    			} else {
    				if(nf==nff->ch[1]) rot(nf,1);
    				rot(o,1);
    			}
    		}
    		o->maintain();
    	}
    	void Access(Node* o) {
    		Node *son=null;
    		while(o!=null) {
    			splay(o);
    			o->ch[1]=son;
    			o->maintain();
    			son=o; o=o->fa;
    		}
    	}
    	void evert(Node* o) {
    		Access(o); 
    		splay(o);
    		o->reverse();
    	}
    	void Link(Node* u,Node* v) {
    		evert(u);
    		u->fa=v;
    	}
    	void Cut(Node* u,Node* v) {
    		evert(u);
    		Access(v),splay(v);
    		v->ch[0]=u->fa=null;
    		v->maintain();
    	}
    	Node* find(Node* o) {
    		while(o->fa!=null) o=o->fa;
    		return o;
    	}
    
    }
    using namespace LCT ;
    

    2-SAT:

    //2-sat
    struct TwoSAT {
    	int n;
    	vector<int> g[N<<1];
    	int st[N<<1],mark[N<<1],top;
    	
    	bool dfs(int x) {
    		if(mark[x^1]) return 0;
    		if(mark[x]) return 1;
    		mark[x]=1;
    		st[++top]=x;
    		for(int i=0;i<g[x].size();i++)
    			if(!dfs(g[x][i])) return 0;
    		return 1;
    	}
    	void init(int n) {
    		this->n=n;
    		for(int i=0;i<2*n;i++) g[i].clear();
    		memset(mark,0,sizeof(mark));
    	}
    	void addc(int x,int xval,int y,int yval) {
    		x=x*2+xval;
    		y=y*2+yval;
    		g[x^1].push_back(y);
    		g[y^1].push_back(x);
    	}
    	bool solve() {
    		for(int i=0;i<2*n;i+=2) {
    			if(!mark[i]&&!mark[i+1]) {
    				top=0;
    				if(!dfs(i)) {
    					while(top) mark[st[top--]]=0;
    					if(!dfs(i+1)) return 0;
    				}
    			}
    		}
    		return 1;
    	}
    	
    } s;
    

      

    有向图的强联通分量:

    //tarjan求SCC 
    struct Edge {
    	int v,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v) 
    {
    	e[++en]=(Edge){v,front[u]}; front[u]=en;
    }
    
    int n,top,dfn;
    int st[N],sccno[N],scc_cnt,pre[N],lowlink[N];
    
    void tarjan(int u)
    {
    	pre[u]=lowlink[u]=++dfn;
    	st[++top]=u;
    	trav(u,i) {
    		int v=e[i].v;
    		if(!pre[v]) {
    			tarjan(v);
    			lowlink[u]=min(lowlink[u],lowlink[v]);
    		} else 
    		if(!sccno[v]) 
    			lowlink[u]=min(lowlink[u],pre[v]);
    	}
    	if(lowlink[u]==pre[u]) {
    		scc_cnt++;
    		for(;;) {
    			int x=st[top--];
    			sccno[x]=scc_cnt;
    			if(x==u) break;
    		}
    	}
    }
    

    无向图的边的双连通分量:

    //BCC
    struct Edge {
    	int u,v,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v) 
    {
    	e[++en]=(Edge){u,v,front[u]}; front[u]=en;
    }
    
    Edge st[N];
    vector<int> bcc[N];
    int pre[N],iscut[N],bccno[N],top,dfn,bcc_cnt;
    
    int dfs(int u,int fa)
    {
    	int lowu=pre[u]=++dfn;
    	int child=0;
    	trav(u,i) {
    		int v=e[i].v;
    		Edge E=e[i];
    		if(!pre[v]) {
    			st[++top]=E;
    			child++;
    			int lowv=dfs(v,u);
    			lowu=min(lowu,lowv);
    			if(lowv>=pre[u]) {
    				iscut[u]=1;
    				bcc_cnt++;
    				for(;;) {
    					Edge x=st[top--];
    					if(bccno[x.u]!=bcc_cnt) {
    						bccno[x.u]=bcc_cnt; 
    						bcc[bcc_cnt].push_back(x.u);
    					}
    					if(bccno[x.v]!=bcc_cnt) {
    						bccno[x.v]=bcc_cnt; 
    						bcc[bcc_cnt].push_back(x.v);
    					}
    					if(x.u==u&&x.v==v) break;
    				}
    			}
    		} else 
    		if(pre[v]<pre[u] && v!=fa) {
    			st[++top]=E;
    			lowu=min(lowu,pre[v]);
    		}
    	}
    	if(fa<0&&child==1) iscut[u]=0;
    	return lowu;
    }
    

      

    最短路:

    //spfa
    
    struct Edge {
    	int v,w,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v,int w) 
    {
    	e[++en]=(Edge){v,w,front[u]}; front[u]=en;
    }
    
    queue<int> q;
    int inq[N],dis[N];
    void spfa(int s)
    {
    	dis[s]=0; inq[s]=1;
    	q.push(s);
    	while(!q.empty()) {
    		int u=q.front(); q.pop();
    		inq[u]=0;
    		trav(u,i) {
    			int v=e[i].v;
    			if(dis[v]>dis[u]+e[i].w) {
    				dis[v]=dis[u]+e[i].w;
    				if(!inq[v]) {
    					inq[v]=1;
    					q.push(v);
    				}
    			}
    		}
    	}
    }
    
    //dijkstra
    
    struct Node {
        int id,dis;
        bool operator < (const Node& rhs) const
        {
            return dis>rhs.dis;
        }
    };
    
    priority_queue<Node> q;
    int n,m,s;
    int vis[N],dis[N];
    
    void dijkstra(int s)
    {
    	FOR(i,1,n) dis[i]=inf;
        dis[s]=0; q.push((Node){s,0});
        while(!q.empty()) {
            int u=q.top().id;
            q.pop();
            if(vis[u]) continue;
            vis[u]=1;
            trav(u,i) {
                int v=e[i].v;
                if(dis[v]>dis[u]+e[i].w) {
                    dis[v]=dis[u]+e[i].w;
                    q.push((Node){v,dis[v]});
                }
            }
        }
    }
    

      

      

    最小生成树:

    //Kruskal 
    
    int fa[N];
    int find(int u)
    {
    	if(!fa[u] || u==fa[u]) return fa[u]=u;
    	return fa[u]=find(fa[u]);
    }
    
    struct Edge {
    	int u,v,w;
    	bool operator < (const Edge& rhs) const
    	{
    		return w<rhs.w;
    	}
    }e[M];
    int tot;
    
    void Kruskal()
    {
    	sort(e+1,e+tot+1);
    	for(int i=1;i<=tot;i++) {
    		int u=e[i].u,v=e[i].v;
    		int x=find(u),y=find(v);
    		if(x!=y) {
    			fa[x]=y;
    			//加入树边(u,v) 
    		}
    	}
    }
    

      

    最大流:

    //Dinic算法求最大流 
    struct Edge {
    	int u,v,cap,flow;
    };
    struct Dinic {
    	int d[N],cur[N],vis[N];
    	vector<Edge> es;
    	vector<int> g[N];
    	queue<int> q;
    	
    	void AddEdge (int u,int v,int w) {
    		es.push_back((Edge){u,v,w,0});
    		es.push_back((Edge){v,u,0,0});
    		int m=es.size();
    		g[u].push_back(m-2);
    		g[v].push_back(m-1);
    	}
    	bool bfs(int s,int t) {
    		memset(vis,0,sizeof(vis));
    		d[s]=0; vis[s]=1;
    		q.push(s);
    		while(!q.empty()) {
    			int u=q.front(); q.pop();
    			FOR(i,0,(int)g[u].size()-1) {
    				Edge& e=es[g[u][i]];
    				int v=e.v;
    				if(e.cap>e.flow&&!vis[v]) {
    					vis[v]=1;
    					d[v]=d[u]+1;
    					q.push(v);
    				}
    			}
    		}
    		return vis[t];
    	}
    	int dfs(int u,int a,int t) {
    		if(u==t||a==0) return a;
    		int flow=0,f;
    		for(int& i=cur[u];i<g[u].size();i++) {
    			Edge& e=es[g[u][i]];
    			int v=e.v;
    			if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow),t))>0) {
    				e.flow+=f;
    				es[g[u][i]^1].flow-=f;
    				flow+=f,a-=f;
    				if(!a) break;
    			}
    		}
    		return flow;
    	}
    	int maxflow(int s,int t) {
    		int flow=0;
    		while(bfs(s,t)) {
    			memset(cur,0,sizeof(cur));
    			flow+=dfs(s,inf,t);
    		}
    		return flow;
    	}
    } dc;
    

      

    最小费用最大流:

    /最短路算法求最小费用最大流 
    struct Edge {
    	int u,v,cap,flow,cost;
    	Edge(int _,int __,int ___,int ____,int _____)
    	{ u=_,v=__,cap=___,flow=____,cost=_____; }
    };
    
    struct MCMF {
    	int n,m,s,t;
    	int d[N],p[N],a[N],inq[N];
    	vector<Edge> es;
    	vector<int> g[N];
    	queue<int> q;
    	void init(int n) {
    		this->n=n;
    		es.clear();
    		for(int i=0;i<=n;i++) g[i].clear();
    	}
    	void AddEdge(int u,int v,int w,int c) {
    		es.push_back(Edge(u,v,w,0,c));
    		es.push_back(Edge(v,u,0,0,-c));
    		int m=es.size();
    		g[u].push_back(m-2);
    		g[v].push_back(m-1);
    	}
    	bool spfa(int s,int t,ll& flow,ll& cost) {
    		memset(inq,0,sizeof(inq));
    		for(int i=0;i<=n;i++) d[i]=inf;
    		inq[s]=1; d[s]=p[s]=0; a[s]=inf; 
    		q.push(s);
    		while(!q.empty()) {
    			int u=q.front(); q.pop();
    			inq[u]=0;
    			for(int i=0;i<g[u].size();i++) {
    				Edge& e=es[g[u][i]];
    				int v=e.v;
    				if(d[v]>d[u]+e.cost && e.cap>e.flow) {
    					d[v]=d[u]+e.cost;
    					a[v]=min(a[u],e.cap-e.flow);
    					p[v]=g[u][i];
    					if(!inq[v])
    						inq[v]=1 , q.push(v);
    				}
    			}
    		}
    		if(d[t]==inf) return 0;
    		flow+=a[t],cost+=a[t]*d[t];
    		for(int x=t;x!=s;x=es[p[x]].u) {
    			es[p[x]].flow+=a[t];
    			es[p[x]^1].flow-=a[t];
    		}
    		return 1;
    	}
    	void mcmf(int s,int t,ll& cost,ll& flow) {
    		flow=cost=0;
    		while(spfa(s,t,cost,flow)) ;
    	}
    } mc;
    

     

    KM算法:

    //KM算法求二分图的最佳完美匹配 
    struct KM {
    	int slack[N],res[N];
    	int l[N],r[N],lx[N],rx[N],g[N][N];
    	
    	void clear(int n) {
    		for(int i=1;i<=n;i++) {
    			res[i]=0;
    			for(int j=1;j<=n;j++) g[i][j]=-1;
    		}
    	}
    	bool find(int x,int n) {
    		lx[x]=1;
    		for(int i=1;i<=n;i++)
    			if(!rx[i]&&g[x][i]!=-1) {
    				int tmp=g[x][i]-l[x]-r[i];
    				if(!tmp) {
    					rx[i]=1;
    					if(!res[i]||find(res[i],n)) {
    						res[i]=x;
    						return 1;
    					}
    				} else 
    					slack[i]=min(slack[i],tmp);
    			}
    		return 0;
    	}
    	int solve(int n) {
    		if(!n) return 0;
    		for(int i=1;i<=n;i++) r[i]=0;
    		for(int i=1;i<=n;i++) {
    			l[i]=INF;
    			for(int j=1;j<=n;j++) if(g[i][j]!=-1)
    				l[i]=min(l[i],g[i][j]);
    		}
    		for(int i=1;i<=n;i++) {
    			for(int j=1;j<=n;j++) slack[j]=INF;
    			for(;;) {
    				for(int j=1;j<=n;j++) lx[j]=rx[j]=0;
    				if(find(i,n)) break;
    				int mini=INF;
    				for(int i=1;i<=n;i++) if(!rx[i])
    					mini=min(mini,slack[i]);
    				for(int i=1;i<=n;i++) {
    					if(lx[i]) l[i]+=mini;
    					if(rx[i]) r[i]-=mini;
    					else slack[i]-=mini;
    				}
    			}
    		}
    		int ans=0;
    		for(int i=1;i<=n;i++)
    			ans+=l[i]+r[i];
    		return ans;
    	}
    } km; 
    

      

     

    LCA:

    //倍增法求LCA
    //倍增法可以在线构造 比较灵活 
    struct Edge {
    	int v,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v) 
    {
    	e[++en]=(Edge){v,front[u]}; front[u]=en;
    }
    
    int fa[N][D],dep[N];
    
    void dfs(int u) 
    {
    	for(int i=1;i<D;i++)
    		fa[u][i]=fa[fa[u][i-1]][i-1];
    	trav(u,i) {
    		int v=e[i].v;
    		if(v!=fa[u][0]) {
    			fa[v][0]=u;
    			dep[v]=dep[u]+1;
    			dfs(v);
    		}
    	}
    }
    int lca(int u,int v)
    {
    	if(dep[u]<dep[v]) swap(u,v);
    	int t=dep[u]-dep[v];
    	for(int i=0;i<D;i++)
    		if(t&(1<<i)) u=fa[u][i];
    	if(u==v) return u;
    	for(int i=D-1;i>=0;i--)
    		if(fa[u][i]!=fa[v][i])
    			u=fa[u][i],v=fa[v][i];
    	return fa[u][0];
    }
    
    //树链剖分求LCA
    //比较快 
    struct Edge {
    	int v,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v)
    {
    	e[++en]=(Edge){v,front[u]}; front[u]=en;
    }
    
    int fa[N],top[N],siz[N],dep[N],son[N];
    void dfs1(int u)
    {
    	siz[u]=1; son[u]=0;
    	trav(u,i) {
    		int v=e[i].v;
    		if(v!=fa[u]) {
    			fa[v]=u;
    			dep[v]=dep[u]+1;
    			dfs1(v);
    			siz[u]+=siz[v];
    			if(siz[v]>siz[son[u]]) son[u]=v;
    		}
    	}
    }
    void dfs2(int u,int tp)
    {
    	top[u]=tp; 
    	if(son[u]) dfs2(son[u],tp);
    	trav(u,i)
    		if(e[i].v!=fa[u]&&e[i].v!=son[u])
    			dfs2(e[i].v,e[i].v);
    }
    int lca(int u,int v)
    {
    	while(top[u]!=top[v]) {
    		if(dep[top[u]]<dep[top[v]]) swap(u,v);
    		u=fa[top[u]];
    	}
    	return dep[u]<dep[v]? u:v;
    }
    

      

    树链剖分:

    //树链剖分
    struct Edge {
    	int v,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v)
    {
    	e[++en]=(Edge){v,front[u]}; front[u]=en;
    }
    
    int fa[N],top[N],siz[N],dep[N],son[N],bl[N],dfn;
    void dfs1(int u)
    {
    	siz[u]=1; son[u]=0;
    	trav(u,i) {
    		int v=e[i].v;
    		if(v!=fa[u]) {
    			fa[v]=u;
    			dep[v]=dep[u]+1;
    			dfs1(v);
    			siz[u]+=siz[v];
    			if(siz[v]>siz[son[u]]) son[u]=v;
    		}
    	}
    }
    void dfs2(int u,int tp)
    {
    	top[u]=tp; bl[u]=++dfn;
    	if(son[u]) dfs2(son[u],tp);
    	trav(u,i)
    		if(e[i].v!=fa[u]&&e[i].v!=son[u])
    			dfs2(e[i].v,e[i].v);
    }
    //以合适的数据结构T维护重链 
    int ans;
    int query(int u,int v)
    {
    	while(top[u]!=top[v]) {
    		if(dep[top[u]]<dep[top[v]]) swap(u,v);
    		ans<-query(T,bl[top[u]],bl[u]);
    		u=fa[top[u]];
    	}
    	if(u==v) return ;
    	if(dep[u]>dep[v]) swap(u,v);
    	ans<-query(T,bl[u],bl[v]);
    	<-ans
    }
    //类似-查询树上任意两节点的方法 
    void modify() {}
    

      

    点分治:

    //点分治 
    struct Edge {
    	int v,nxt;
    }e[M];
    int en=1,front[N];
    void adde(int u,int v)
    {
    	e[++en]=(Edge){v,front[u]}; front[u]=en;
    }
    
    int rt,n,size,vis[N],siz[N],f[N],dep[N];
    
    void get_root(int u,int fa)
    {
    	siz[u]=1; f[u]=0;
    	trav(u,i) {
    		int v=e[i].v;
    		if(v!=fa) {
    			get_root(v,u);
    			siz[u]+=siz[v];
    			if(siz[v]>f[u]) f[u]=siz[v];
    		}
    	}
    	f[u]=max(f[u],size-siz[u]);
    	if(f[u]<f[rt]) rt=u;
    }
    void solve(int u)
    {
    	vis[u]=1;
    	//计算经过根u的信息 
    	trav(u,i) if(!vis[e[i].v])
    	{
    		//统计当前子树信息
    		//与前i-1个子树信息结合计算贡献
    		//将当前子树信息加入前i-1个子树信息 
    	}
    	trav(u,i) if(!vis[e[i].v]) {
    		int v=e[i].v;
    		size=siz[v]; rt=0;
    		get_root(v,-1);
    		solve(rt); 
    	}
    }
    int main()
    {
    	//blabla
    	size=f[0]=n;
    	rt=0; get_root(rt,-1);
    	solve(rt);
    }
    

      

    字符串

    KMP:

    //KMP算法 
    int f[N]; char s[N];
    void get_fail()
    {
        int j=0;
        int n=strlen(s+1);
        for(int i=2;i<=n;i++) {
            while(j&&s[j+1]!=s[i]) j=f[j];
            if(s[j+1]==s[i]) j++;
            f[i]=j;
        }
    }
    

      

    AC自动机:

    //AC自动机 
    struct AC_auto {
    	int sz,ch[N][26],f[N],val[N];
    	AC_auto() {
    		sz=1;
    		memset(ch,0,sizeof(ch));
    	}
    	void insert(char* s) {
    		int u=0;
    		for(int i=0;s[i];i++) {
    			int c=s[i]-'a';
    			if(!ch[u][c]) ch[u][c]=++sz;
    			u=ch[u][c];
    		}
    		val[u]=1;
    	}
    	void get_fail() {
    		queue<int> q;
    		f[0]=0;
    		for(int c=0;c<26;c++)
    			if(ch[0][c]) f[ch[0][c]]=0,q.push(ch[0][c]);
    		while(!q.empty()) {
    			int qr=q.front(); q.pop();
    			for(int c=0;c<26;c++) {
    				int u=ch[qr][c];
    				if(!u) continue;
    				q.push(u);
    				int v=f[qr];
    				while(v&&!ch[v][c]) v=f[v];
    				if(val[ch[v][c]]) val[u]=1;
    				f[u]=ch[v][c];
    			}
    		}
    	}
    }; 
    

      

      

    后缀自动机:

    //后缀自动机SAM 
    struct SAM {
    	int sz,last,fa[N],ch[N][26],l[N];
    	SAM() {
    		sz=0; last=++sz;
    		memset(l,0,sizeof(l));
    		memset(fa,0,sizeof(fa));
    	}
    	void Add(int c) {
    		int np=++sz,p=last; last=np;
    		l[np]=l[p]+1;
    		for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
    		if(!p) fa[np]=1;
    		else {
    			int q=ch[p][c];
    			if(l[q]==l[p]+1) fa[np]=q;
    			else {
    				int nq=++sz; l[nq]=l[p]+1;
    				memcpy(ch[nq],ch[q],sizeof(ch[q]));
    				fa[nq]=fa[q];
    				fa[q]=fa[np]=nq;
    				for(;q==ch[p][c];p=fa[p]) ch[p][c]=nq;
    			}
    		}
    	}
    	//do some other things
    	
    } sam;
    

      

    后缀数组:

    //后缀数组
    #define rep(a,b,c) for(int a=(b);a>=(c);a--)
    #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
    char s[N];
    int c[N],t[N],t2[N],height[N],rank[N],sa[N];
    void build_sa(int m,int n) {
    	int *x=t,*y=t2,p,k;
    	FOR(i,0,m-1) c[i]=0;
    	FOR(i,0,n-1) c[x[i]=s[i]]++;
    	FOR(i,0,m-1) c[i]+=c[i-1];
    	rep(i,n-1,0) sa[--c[x[i]]]=i;
    	
    	for(k=1;k<=n;k<<=1) {
    		p=0;
    		FOR(i,n-k,n-1) y[p++]=i;
    		FOR(i,0,n-1) if(sa[i]>=k) y[p++]=sa[i]-k;
    		
    		FOR(i,0,m-1) c[i]=0;
    		FOR(i,0,n-1) c[x[y[i]]]++;
    		FOR(i,0,m-1) c[i]+=c[i-1];
    		rep(i,n-1,0) sa[--c[x[y[i]]]]=y[i];
    		
    		swap(x,y);
    		p=1; x[sa[0]]=0;
    		FOR(i,1,n-1)
    			x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]? p-1:p++;
    		if(p>=n) break;
    		m=p;
    	}
    } 
    void get_height(int n)
    {
    	FOR(i,0,n-1) rank[sa[i]]=i;
    	int k=0;
    	FOR(i,0,n-1) {
    		if(k) k--;
    		int j=sa[rank[i]-1];
    		while(s[i+k]==s[j+k]) k++;
    		height[rank[i]]=k;
    	}
    }
    

      

    Manacher:

    //Manacher算法 
    char s[N],a[N];
    int p[N];
    void Add(int l,int r)
    {
    	l=l/2,r=r/2-1;
    	if(l>r) return ;
    	//q[++tot]=(Seg){l,r};
    	//[l,r]为一个极大回文串 
    }
    void Manacher()
    {
    	int n=strlen(s+1);
    	int m=n*2+1;
    	for(int i=1;i<=n;i++) {
    		a[i<<1]=s[i];
    		a[i<<1|1]='#';
    	}
    	a[0]='+',a[1]='#',a[m+1]='-';
    	int mx=0,id;
    	for(int i=1;i<=m;i++) {
    		if(mx>i) p[i]=min(mx-i,p[id*2-i]);
    		else p[i]=1;
    		while(a[i-p[i]]==a[i+p[i]]) p[i]++;
    		Add(i-p[i],i+p[i]);
    		if(p[i]+i>mx) mx=i+p[i],id=i;
    	}
    }
    

      

    计算几何

    计算几何基础知识:

    //计算几何基础
    
    const double eps = 1e-10;
    int dcmp(double x) {
    	if(fabs(x)<eps) return 0; else return x<0? -1:1;
    }
    
    struct Pt { 
    	double x,y;
    	Pt(double x=0,double y=0):x(x),y(y) {}
    };
    typedef Pt vec;
    
    vec operator - (Pt A,Pt B) { return vec(A.x-B.x,A.y-B.y); }
    vec operator + (vec A,vec B) { return vec(A.x+B.x,A.y+B.y); }
    vec operator * (vec A,double p) { return vec(A.x*p , A.y*p); }
    bool operator < (const Pt& a,const Pt& b) {
    	return a.x<b.x || (a.x==b.x && a.y<b.y);
    }
    bool operator == (const Pt& a,const Pt& b) {
    	return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
    }
    
    double cross(vec A,vec B) { return A.x*B.y-A.y*B.x; }
    double Dot(vec A,vec B) { return A.x*B.x+A.y*B.y; }
    double Len(vec A) { return sqrt(Dot(A,A)); }
    double Angle(vec A,vec B) { return acos(Dot(A,B)/Len(A)/Len(B)); }
    
    //逆时针旋转rad角度 
    vec rotate(vec A,double rad) { 
    	return vec(A.x*cos(rad)-A.y*sin(rad) , A.x*sin(rad)+A.y*cos(rad));
    }
    //法向量 左转90度 长度归1
    vec Normal(vec A)
    {
    	double L=Len(A);
    	return vec(-A.y/L,A.x/L);
    }
    //判断点在线段上 
    bool OnSeg(Pt P,Pt a1,Pt a2) {
    	return dcmp(cross(a1-P,a2-P))==0 && dcmp(Dot(a1-P,a2-P))<0;
    }
    //直线交点 
    Pt LineIntersection(Pt P,vec v,Pt Q,vec w) {
    	vec u=P-Q;
    	double t=cross(w,u)/cross(v,w);
    	return P+v*t;
    }
    double DistoLine(Pt P,Pt A,Pt B) {
    	vec v1=B-A,v2=P-A;
    	return fabs(cross(v1,v2))/Len(v1);
    }
    //线段不含端点 判断相交 
    bool SegIntersection(Pt a1,Pt a2,Pt b1,Pt b2) {
    	double c1=cross(a2-a1,b1-a1) , c2=cross(a2-a1,b2-a1) ,
    		   c3=cross(b2-b1,a1-b1) , c4=cross(b2-b1,a2-b1);
    	return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
    	// b1 b2在线段a1a2的两侧  a1 a2在线段b1b2的两侧  规范相交
    }
    //线段含端点 判断线段严格相交 
    bool SegInter(Pt s1, Pt e1, Pt s2, Pt e2) {
        if( min(s1.x, e1.x) <= max(s2.x, e2.x) &&
            min(s1.y, e1.y) <= max(s2.y, e2.y) &&
            min(s2.x, e2.x) <= max(s1.x, e1.x) &&
            min(s2.y, e2.y) <= max(s1.y, e1.y) &&
            cross(e1-s1,s2-s1) * cross(e1-s1,e2-s1) <= 0 &&
            cross(e2-s2,s1-s2) * cross(e2-s2,e1-s2) <= 0 
    	  ) return true;
        return false;
    }
    //点到线段的距离 
    double DistoSeg(Pt P,Pt A,Pt B) {
    	if(A==B) return Len(P-A);
    	vec 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);
    }
    //多边形面积 
    double PolygonArea(Pt* p,int n)
    {
    	double S=0;
    	for(int i=1;i<n-1;i++)
    		S+=cross(p[i]-p[0],p[i+1]-p[0]);
    	return S/2;
    }
    

      

    凸包:

    //凸包
    const int N = 400000+10; 
    const double PI = acos(-1.0);
    const double eps = 1e-12;
    
    int dcmp(double x) {
    	if(fabs(x)<eps) return 0; else return x<0? -1:1;
    }
    
    struct Pt {
    	double x,y;
    	Pt(double x=0,double y=0) :x(x),y(y) {};
    };
    typedef Pt vec;
    
    vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
    vec operator + (vec a,vec b) { return vec(a.x+b.x,a.y+b.y); }
    bool operator == (Pt a,Pt b) { 
    	return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
    }
    bool operator < (const Pt& a,const Pt& b) {
    	return a.x<b.x || (a.x==b.x && a.y<b.y);
    }
    
    vec rotate(vec a,double x) {
    	return vec(a.x*cos(x)-a.y*sin(x),a.x*sin(x)+a.y*cos(x));
    }
    double cross(vec a,vec b) { return a.x*b.y-a.y*b.x; }
    double dist(Pt a,Pt b) {
    	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    vector<Pt> ConvexHull(vector<Pt> p) {
    	sort(p.begin(),p.end());
    	p.erase(unique(p.begin(),p.end()),p.end());
    	int n=p.size() , m=0;
    	vector<Pt> ch(n+1);
    	for(int i=0;i<n;i++) {
    		while(m>1 && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
    		ch[m++]=p[i];
    	}
    	int k=m;
    	for(int i=n-2;i>=0;i--) {
    		while(m>k && cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0) m--;
    		ch[m++]=p[i];
    	}
    	if(n>1) m--;
    	ch.resize(m); return ch;
    }
    

      

    半平面交:

    //半平面交
    
    const int N =  305;
    const double bond = 100001;
    const double eps = 1e-10;
    
    struct Pt {
    	double x,y;
    	Pt (double x=0,double y=0):x(x),y(y){}
    };
    typedef Pt vec;
    
    vec operator + (Pt a,Pt b) { return vec(a.x+b.x,a.y+b.y); }
    vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
    vec operator * (Pt a,double p) { return vec(a.x*p,a.y*p); }
    
    double cross(Pt a,Pt b) { return a.x*b.y-a.y*b.x; }
    
    struct Line {
    	Pt p; vec v; double ang;
    	Line () {}
    	Line (Pt p,vec v) :p(p),v(v){ ang=atan2(v.y,v.x); }
    	bool operator < (const Line& rhs) const {
    		return ang<rhs.ang;
    	}
    };
    
    bool onleft(Line L,Pt p) { return cross(L.v,p-L.p)>0; }
    Pt LineInter(Line a,Line b) 
    {
    	vec u=a.p-b.p;
    	double t=cross(b.v,u)/cross(a.v,b.v);
    	return a.p+a.v*t;
    }
    vector<Pt> HPI(vector<Line> L)
    {
    	int n=L.size();
    	sort(L.begin(),L.end());
    	int f,r;
    	vector<Pt> p(n) , ans;
    	vector<Line> q(n);
    	q[f=r=0]=L[0];
    	for(int i=1;i<n;i++) {
    		while(f<r&&!onleft(L[i],p[r-1])) r--;
    		while(f<r&&!onleft(L[i],p[f])) f++;
    		q[++r]=L[i];
    		if(fabs(cross(q[r].v,q[r-1].v))<eps) {
    			r--;
    			if(onleft(q[r],L[i].p)) q[r]=L[i];
    		}
    		if(f<r) p[r-1]=LineInter(q[r-1],q[r]);
    	}
    	while(f<r&&!onleft(q[f],p[r-1])) r--;
    	if(r-f<=1) return ans;
    	p[r]=LineInter(q[r],q[f]);
    	for(int i=f;i<=r;i++) ans.push_back(p[i]);
    	return ans; 
    }
    

      

  • 相关阅读:
    hdu 4027 Can you answer these queries?
    hdu 4041 Eliminate Witches!
    hdu 4036 Rolling Hongshu
    pku 2828 Buy Tickets
    hdu 4016 Magic Bitwise And Operation
    pku2886 Who Gets the Most Candies?(线段树+反素数打表)
    hdu 4039 The Social Network
    hdu 4023 Game
    苹果官方指南:Cocoa框架(2)(非原创)
    cocos2d 中 CCNode and CCAction
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5354305.html
Copyright © 2011-2022 走看看