1. 程式人生 > 實用技巧 >2020.11.19考試學習筆記

2020.11.19考試學習筆記

IO

快讀

 #pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
namespace in{
	char buf[1<<21],*p1=buf,*p2=buf;
	inline int getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
	template <typename T>inline void read(T& t){
		t=0;int f=0;char ch=getc();while (!isdigit(ch)){if(ch=='-')f = 1;ch=getc();}
	    while(isdigit(ch)){t=t*10+ch-48;ch = getc();}if(f)t=-t;
	}
	template <typename T,typename... Args> inline void read(T& t, Args&... args){read(t);read(args...);}
}
namespace out{
	char buffer[1<<21];int p1=-1;const int p2 = (1<<21)-1;
	inline void flush(){fwrite(buffer,1,p1+1,stdout),p1=-1;}
	inline void putc(const char &x) {if(p1==p2)flush();buffer[++p1]=x;}
	template <typename T>void write(T x) {
		static char buf[15];static int len=-1;if(x>=0){do{buf[++len]=x%10+48,x/=10;}while (x);}else{putc('-');do {buf[++len]=-(x%10)+48,x/=10;}while(x);}
		while (len>=0)putc(buf[len]),--len;
	}
}
using namespace std;

signed main(){
	out::flush();
	return 0;
}

圖論

SPFA

const int maxn=10010;
const int maxm=500010;
struct spfa{
	int s,t,c;bool vis[maxn];
	int head[maxn],path[maxn];
	struct node{
	    int nxt,to,w;
	}a[maxm<<1];
	inline int relax(int u,int v,int w){
	    if(path[v]>path[u]+w){
	        path[v]=path[u]+w;
	        return 1;
	    }return 0;
	}
	inline void add(int u,int v,int w){a[c].to=v;a[c].w=w;a[c].nxt=head[u];head[u]=c++;}
	inline void init(int _s,int _t){s=_s,t=_t;memset(head,0,sizeof head);c=1;}
	void deal(){
	    int u,v,num=0;long long x=0;list<int> q;
	    memset(path,0x3f,sizeof path);
	    memset(vis,false,sizeof vis);
	    path[s]=0;vis[s]=true;q.push_back(s);num++;
	    while(!q.empty()){
	        u=q.front();q.pop_front();
	        num--;x-=path[u];
	        while(num&&path[u]>x/num){q.push_back(u);u=q.front();q.pop_front();}
	        vis[u]=false;
	        for(int i=head[u];i;i=a[i].nxt){
	            v=a[i].to;
	            if(relax(u,v,a[i].w)&&!vis[v]){
	                if(!q.empty()&&path[v]<path[q.front()])q.push_front(v);
	                else q.push_back(v);num++;x+=path[v];vis[v]=true;
	            }
	        }
	    }
	}	
};

Dinic

const int maxn=4010,maxe=100010*2;
struct Graph{
	struct node{
		int v,w,nxt;
	}e[maxe<<1];
	int head[maxn],cur[maxn],tot;
	int dis[maxn];
	int s,t;
	void init(int _s,int _t){s=_s,t=_t;tot=1;memset(head,0,sizeof head);}
	Graph(int _s=0,int _t=0){init(_s,_t);}
	void add(int u,int v,int w){
		//printf("%d %d %d\n",u,v,w);
		e[++tot]=(node){v,w,head[u]},head[u]=tot;
		e[++tot]=(node){u,0,head[v]},head[v]=tot;
	}
	#define v e[i].v
	inline bool bfs(){
		queue<int>q;
		memset(dis,0,sizeof dis);
		memcpy(cur,head,sizeof head);
		dis[s]=1;q.push(s);
		while(q.size()){
			int u=q.front();q.pop();
			for(int i=head[u];i;i=e[i].nxt)
				if(!dis[v]&&e[i].w){
					dis[v]=dis[u]+1,q.push(v);
					if(v==t)return true;
				}
		}
		return  false;
	}
	int dfs(int u,int flow){
		if(u==t)return flow;
		int rest=flow;
		for(int i=cur[u];i&&rest;i=e[i].nxt){
			if(dis[v]==dis[u]+1&&e[i].w){
				int tmp=dfs(v,min(rest,e[i].w));
				rest-=tmp,e[i].w-=tmp,e[i^1].w+=tmp;
			}
			cur[u]=i;
		}
		if(rest==0)dis[u]=-1;
		return flow-rest;
	}
	#undef v
	int dinic(){
		int ans=0;
		while(bfs())
			while(int sth=dfs(s,2e9))
				ans+=sth;
		return ans;
	}
}G; 

MincostMaxflow

const int maxn=100005;
const int maxe=100005;
struct Graph{
	int s,t;
	int dis[maxn],pre[maxn],lste[maxn],flow[maxn];
	bool inq[maxn];
	struct node{
		int v,w,cost,nxt;
		node(int _v=0,int _w=0,int _c=0,int _n=0){v=_v,w=_w,cost=_c,nxt=_n;}
	}e[maxe];
	int tot,head[maxn];
	void init(int _s,int _t){
		memset(head,0,sizeof head);
		tot=1;s=_s,t=_t;
	}
	inline void add(int u,int v,int w,int c){
		e[++tot]=node(v,w,c,head[u]);head[u]=tot;
		e[++tot]=node(u,0,-c,head[v]);head[v]=tot;
	}
	bool spfa(){
		queue<int>q;
		memset(dis,63,sizeof dis);
		memset(flow,63,sizeof flow);
		memset(inq,0,sizeof inq);
		dis[s]=0,pre[t]=-1;q.push(s);
		while(!q.empty()){
			int u=q.front();q.pop();inq[u]=0;
			#define v e[i].v
			for(int i=head[u];i;i=e[i].nxt){
				if(e[i].w>0&&dis[v]>dis[u]+e[i].cost){
					dis[v]=dis[u]+e[i].cost;
					pre[v]=u,lste[v]=i;//lste 表示頂點v是由哪條邊過來的
					flow[v]=min(flow[u],e[i].w);
					if(!inq[v])inq[v]=1,q.push(v);
				}
			}
			#undef v
		}
		return pre[t]!=-1;
	}
	pair<int,int> mcmf(){
		int mincost=0,maxflow=0;
		while(spfa()){
			int u=t;
			maxflow+=flow[t],mincost+=flow[t]*dis[t];
			while(u!=s){
				int E=lste[u];
				e[E].w-=flow[t],e[E^1].w+=flow[t];
				u=pre[u];
			}
		}
		return make_pair(mincost,maxflow);
	}
}G;

數學

自適應辛普森法

struct Simpson{
	double (*f)(double);
	double Eps;
	Simpson(double (*_f)(double),double _E){f=_f;Eps=_E;}
	inline double simpson(double l,double r){
		double mid=(l+r)/2;
		return (f(l)+4*f(mid)+f(r))*(r-l)/6;
	}
	double asr(double l,double r,double eps,double ans){
		double mid=(l+r)/2;
		double l_=simpson(l,mid),r_=simpson(mid,r);
		if(fabs(l_+r_-ans)<=15*eps)return l_+r_+(l_+r_-ans)/15;
		return asr(l,mid,eps/2,l_)+asr(mid,r,eps/2,r_);
	}
	double asr(double l,double r){
		return asr(l,r,Eps,simpson(l,r));
	}
};

凸包

namespace Convex_Hull{
	#define sq(x) (x)*(x)
	struct node{
		double x,y;
	}p[1000000+1000],s[1000000+1000];
	int n=0,cnt;
	double check(node a1,node a2,node b1,node b2){
		return (a2.x-a1.x)*(b2.y-b1.y)-(a2.y-a1.y)*(b2.x-b1.x);
	}double d(node a,node b){
		return sqrt(sq(a.x-b.x)+sq(a.y-b.y));
	}bool cmp(node p1,node p2){
		double tmp=check(p1,p[1],p2,p[1]);
		if(tmp>0)return 1;
		else if(tmp==0&&d(p[0],p1)<d(p[0],p2))return 1;
		return 0;
	}
	void add(double x,double y){
		n++;
		p[n].x=x,p[n].y=y;
		if(p[n].y<p[1].y)swap(p[n],p[1]);
	}
	void deal(){
		sort(p+2,p+1+n,cmp);
		s[1]=p[1];cnt=1;
		for(int i=2;i<=n;i++){
			while(cnt>1&&check(s[cnt-1],s[cnt],s[cnt],p[i])<=0)
				cnt--;
			s[++cnt]=p[i];
		}s[cnt+1]=p[1];
	}
	double C(){
		double ans=0;
		for(int i=1;i<=cnt;i++)
			ans+=d(s[i],s[i+1]);
		return ans;
	}
};

數論

快速冪

template<class T>T ksm(T a,T b,T c){
	T res=1;
	while(b){
		if(b&1)res=res*a%c;
		a=a*a%c;b>>=1;
	}return res;
}

逆元

template<class T>void exgcd(T a,T b,T &x,T &y){
	if(!b)x=1,y=0;
	else{
		exgcd(b,a%b,x,y);
		T t=x;x=y;
		y=t-a/b*y;
	}
}
template<class T>T inv(T a,T b){
	T x,y;exgcd(a,b,x,y);
	return (x%b+b)%b;
}

BSGS

template<class T>T bsgs(T a,T b,T p){
	unordered_map<T,T>hash;
	b%=p;T t=sqrt(p)+1;
	for(T i=0;i<t;i++)
		hash[b*ksm(a,i,p)%p]=i;
	a=ksm(a,t,p);
	if(!a)return b=0?1:-1;
	for(T i=1;i<=t;i++){
		T val=ksm(a,i,p);
		int j=hash.find(val)==hash.end()?-1:hash[val];
		if(j>=0&&i*t-j>=0)return i*t-j;
	}return -1;
}

exBSGS

template<class T>T ex_bsgs(T a,T b,T p){
	if(b==1||p==1)return -1;
	T na=1,k=0;
	while(T g=__gcd(a,p)){
		if(g==1)break;
		if(b%g)return -1;
		k++;b/=g;p/=g;na=na*(a/g)%p;
		if(na==b)return k;
	}
	long long f=bsgs(a,b*inv(na,p)%p,p);
	if(f==-1)return -1;
	return f+k;
}

資料結構

並查集

const int maxn=1e4+10;
struct DSU{
	int fa[maxn];
	DSU(){for(int i=1;i<maxn;i++)fa[i]=i;}
	int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
	void merge(int x,int y){fa[getfa(y)]=getfa(x);}
};

可持久化線段樹

struct node{
	int l,r,lc,rc;int len,llen,rlen,mlen;
	template<class T>node(T val){
		if(val==1)llen=rlen=mlen=1;
		else llen=rlen=mlen=0;
		len=1;
	}
	node(){llen=rlen=mlen=len=0;}
	node operator+(const node b)const{
		node c;c.len=len+b.len;
		if(r-l+1==mlen)c.llen=mlen+b.llen;
		else c.llen=llen;
		if(b.r-b.l+1==b.mlen)c.rlen=b.mlen+rlen;
		else c.rlen=b.rlen;
		c.mlen=max(rlen+b.llen,max(mlen,b.mlen));
		return c;
	}
	void cpy(node from){
		llen=from.llen;
		rlen=from.rlen;
		mlen=from.mlen;
		len=from.len;
	}
};
template<class A,class B>
struct HJT_Tree{
	A t[maxn*20];B a[maxn];
	B *operator[](const int x){return &a[x];}
	int cnt;HJT_Tree(){cnt=0;}
	int build(int l,int r){
		int x=++cnt;
		t[x].l=l,t[x].r=r;
		if(l==r){
			t[x].cpy(A(a[l]));
			return x;
		}
		int mid=l+r>>1;
		t[x].lc=build(l,mid);
		t[x].rc=build(mid+1,r);
		t[x].cpy(t[t[x].lc]+t[t[x].rc]);
		return x;
	}
	int upd(int lst,int pos,B val){
		int x=++cnt;t[x]=t[lst];
		if(t[x].l==t[x].r){t[x].cpy(A(val));return x;}
		int mid=t[x].l+t[x].r>>1;
		if(pos<=mid)t[x].lc=upd(t[lst].lc,pos,val);
		else t[x].rc=upd(t[lst].rc,pos,val);
		t[x].cpy(t[t[x].lc]+t[t[x].rc]);
		return x;
	}
	A qry(int x,int lq,int rq){
		if(lq<=t[x].l&&t[x].r<=rq)return t[x];
		int mid=t[x].l+t[x].r>>1;
		if(rq<=mid)return qry(t[x].lc,lq,rq);
		if(lq>mid)return qry(t[x].rc,lq,rq);
		return qry(t[x].lc,lq,rq)+qry(t[x].rc,lq,rq);
	}
};
HJT_Tree<node,int>Tree;

Splay

#define clear(x) {f[x]=key[x]=size[x]=recy[x]=son[x][0]=son[x][1]=0;}
#define get(x) (son[f[x]][1]==x)
#define connect(x,y,p) {if(x)f[x]=y;if(y)son[y][p]=x;}
#define update(x) {size[x]=recy[x];size[x]+=size[son[x][0]]+size[son[x][1]];}
template<const int N>
struct Splay{
	int num,root,f[N],key[N],size[N],recy[N],son[N][2];
	void rotate(int x){
		int fa=f[x],ffa=f[fa],p1=get(x),p2=get(fa);
		connect(son[x][p1^1],fa,p1);
		connect(fa,x,p1^1);
		connect(x,ffa,p2);
		update(fa);update(x);
	}
	void splay(int x){
		for(int fa;fa=f[x];rotate(x))
		if(f[fa])rotate(get(x)==get(fa)?fa:x);
		root=x;
	}
	void insert(int x){
		if(!root){
			root=++num;
			key[root]=x;size[root]=recy[root]=1;
			son[root][0]=son[root][1]=0;
			return;
		}
		int now=root,fa=0;
		while(1){
			if(key[now]==x){
				++recy[now];
				update(now);update(fa);
				splay(now);return;
			}
			fa=now,now=son[now][x>key[now]];
			if(!now){
				key[++num]=x;
				size[num]=recy[num]=1;
				f[num]=fa;son[fa][x>key[fa]]=num;
				update(fa);splay(num);
				return;
			}
		}
	}
	int find(int x){
		int now=root,ans=0;
		while(1){
			if(x<key[now]){
				now=son[now][0];
				continue;
			}
			ans+=size[son[now][0]];
			if(x==key[now]){splay(now);return ans+1;}
			ans+=recy[now];now=son[now][1];
		}
	}
	inline int kth(int x){
		int now=root;
		while(1){
		if(son[now][0]&&x<=size[son[now][0]]){
			now=son[now][0];
			continue;
		}
		if(son[now][0])x-=size[son[now][0]];
		if(x<=recy[now])return key[now];
		x-=recy[now];now=son[now][1];
		}
	}
	int pre(){
		int now=son[root][0];
		while(son[now][1])now=son[now][1];
		return now;
	}
	int nxt(){
		int now=son[root][1];
		while(son[now][0])now=son[now][0];
		return now;
	}
	void del(int x){
		find(x);
		if(recy[root]>1){
			recy[root]--;
			update(root);
			return;
		}
		if(!son[root][0]&&!son[root][1]){
			clear(root);root=0;
			return;
		}
		int tmp=root;
		if(!son[root][0]){
			f[root=son[root][1]]=0;
			clear(tmp);return;
		}
		if(!son[root][1]){
			f[root=son[root][0]]=0;
			clear(tmp);return;
		}
		int left=pre();
		splay(left);connect(son[tmp][1],root,1);
		clear(tmp);update(root);
	}
};

可持久化平衡樹

const int N=5e5+100;
namespace tree{
	int n,rt[N],cnt;
	struct node{
		int ch[2];
		int rnd,sz,v;
		//rnd隨機值,sz子節點的個數
		//cnt節點的個數 
	}t[N*50];
	int cpynode(int x){
		t[++cnt]=t[x];
		return cnt;
	}
	int newnode(int x){
		t[++cnt].v=x;t[cnt].sz=1;
		t[cnt].rnd=rand();return cnt;
	}
	#define ls(x) t[(x)].ch[0]
	#define rs(x) t[(x)].ch[1]
	void upd(int k){
		if(k)
			t[k].sz=t[ls(k)].sz+t[rs(k)].sz+1;
	}
	inline void split(int now,int k,int &x,int &y){
		if(!now){x=0,y=0;return;}
		if(t[now].v<=k){
			x=cpynode(now);
			split(rs(x),k,rs(x),y);
		}else{
			y=cpynode(now);
			split(ls(y),k,x,ls(y));
		}upd(x);upd(y);
	}
	inline int merge(int x,int y){
		if(!x||!y)return x+y;//返回不為0的值
		if(t[x].rnd<t[y].rnd){
			int z=cpynode(x);
			rs(z)=merge(rs(z),y);
			upd(z);return z;
		} else{
			int z=cpynode(y);
			ls(z)=merge(x,ls(z));
			upd(z);return z;
		}
	}
	inline void insert(int now,int k){
		int x=0,y=0,z=0;
		split(rt[now],k,x,y);
		z=newnode(k);
		rt[now]=merge(merge(x,z),y);
	}
	inline void del(int now,int k){
		int x=0,y=0,z=0;
		split(rt[now],k,x,y);//先把大於k的結點分離
		split(x,k-1,x,z);//保證z中只有值為k的結點
		z=merge(ls(z),rs(z));//若值為k的結點有多個,則合併後少一	個,如果原本只有一個或者沒有,則返回0,相當於刪除了值為k的點
		rt[now]=merge(merge(x,z),y);//合併復原
	}
	inline int rnk(int now,int k){
	    int x=0,y=0;
	    split(rt[now],k-1,x,y);//以x為根的樹中包含了所有值小於k的結點。
	    return t[x].sz+1;//結點數+1就是k的排名
	}
	inline int kth(int x,int k){
		while(1){
			if(t[ls(x)].sz+1==k)return t[x].v;
			else if(t[ls(x)].sz>=k)x=ls(x);
			else k-=t[ls(x)].sz+1,x=rs(x);
		}
	}
	inline int pre(int now,int k){
		int x=0,y=0,z=0;
		split(rt[now],k-1,x,y);
		if(!x)return -2147483647;
		return kth(x,t[x].sz);
	}
	inline int suf(int now,int k){
		int x=0,y=0,z=0;
		split(rt[now],k,x,y);
		if(!y)return 2147483647;
		return kth(y,1);
	}
}