2020.11.19考試學習筆記
阿新 • • 發佈:2020-11-20
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);
}
}