NOIP考前复习模板

钱逸凡

2018-11-09 14:08:46

Personal

``` #include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<algorithm> #include<vector> #include<cmath> using namespace std; const int inf=1<<30; //////////////////////////////// //////////////////////////////// //读入优化整数 inline long long Read(){ long long x=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x*f; } //读入优化实数 inline double READ(){ double x=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); if(c=='.'){ double a=0.1; c=getchar(); while(c>='0'&&c<='9')x+=a*(c-'0'),c=getchar(),a*=0.1; } return x*f; } /////////////////////////////////// /////////////////////////////////// const int mx=101010;//数组大小 const int N=101100;//点数 const int M=205050;//边数 /////////////////////////////////////////// /////////////////////////////////////////// //树状数组 struct TREE{ #define lowbit(i) i&-i long long tree[mx]; int n; inline void add(int i,int x,long long a[]){ while(i<=n){ a[i]+=x; i+=lowbit(i); } }//单点更新 inline long long querysum(int i,long long a[]){ long long ans=0; while(i>0){ ans+=a[i]; i-=lowbit(i); } return ans; } long long c1[mx],c2[mx];//差分数组,差分的差分数组 inline void LRupdate(int l,int r,int x){ add(l,x,c1),add(r+1,-x,c1); add(l,(l-1)*x,c2),add(r+1,-r*x,c2); }//区间更新 inline long long queryLR(int l,int r){ long long s1=r*querysum(r,c1)-querysum(r,c2); long long s2=(l-1)*querysum(l-1,c1)-querysum(l-1,c2); return s1-s2; } //区间查询 }T1; /////////////////////////////////////////// /////////////////////////////////////////// //线段树 struct T{//对应数组 long long val; long long add; int l; int r; }; struct SegTree{ T tr[mx<<2]; inline void pushdown(int i){ if(tr[i].add){ tr[i<<1].val+=(tr[i<<1].r-tr[i<<1].l+1)*tr[i].add; tr[i<<1].add+=tr[i].add; tr[i<<1|1].val+=(tr[i<<1|1].r-tr[i<<1|1].l+1)*tr[i].add; tr[i<<1|1].add+=tr[i].add; tr[i].add=0; } } long long a[mx];//原数组 void build(int i,int l,int r){ tr[i].l=l,tr[i].r=r; if(l==r){ tr[i].val=a[l]; return; } int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); tr[i].val=tr[i<<1].val+tr[i<<1|1].val; } void update(int i,int l,int r,long long x){ if(tr[i].l>r||l>tr[i].r)return; if(l<=tr[i].l&&tr[i].r<=r){ tr[i].val+=(tr[i].r-tr[i].l+1)*x; tr[i].add+=x; return; } pushdown(i); update(i<<1,l,r,x); update(i<<1|1,l,r,x); tr[i].val=tr[i<<1].val+tr[i<<1|1].val; }//[l,r]更新 long long query(int i,int l,int r){ if(tr[i].l>r||l>tr[i].r)return 0; if(l<=tr[i].l&&tr[i].r<=r)return tr[i].val; pushdown(i); return query(i<<1,l,r)+query(i<<1|1,l,r); }//区间查询 }T2; //////////////////////////////////////////////////// /////////////////////////////////////////////////// //二叉堆 struct HHeap{//每个堆内的元素 int h;//优先级 int pos;//位置等信息 bool operator > (const HHeap &x){ return h<x.h;//因为后面要写dijstra,所以就用小根堆了 // return h>x.h;//大根堆 } }; struct Heap{ #define swap(x,y) x^=y^=x^=y int siz; HHeap heap[mx]; inline void sswap(HHeap &a,HHeap &b){ swap(a.h,b.h); swap(a.pos,b.pos); } void insert(HHeap a){ heap[++siz]=a; int fa,now; now=siz; while(now){ fa=now>>1; if(heap[now]>heap[fa])sswap(heap[now],heap[fa]),now=fa; else break; } }//插入x void pop(){ sswap(heap[siz],heap[1]); siz--; int now=1,son; while((now<<1)<=siz){ son=now<<1; if(son<siz&&heap[son|1]>heap[son])son|=1; if(heap[son]>heap[now])sswap(heap[son],heap[now]),now=son; else break; } } }H; ///////////////////////////////////// ////////////////////////////////////// ////dijstra struct Dijstra{ int n,m; int dist[N],vis[N]; int s;//起点 struct Node{ int v; int val; int next; }node[M]; int top,head[N]; Heap h;//堆 inline void addedge(int u,int v,int val){ node[++top].v=v; node[top].val=val; node[top].next=head[u]; head[u]=top; } void dijstra(){ memset(dist,0x3f,sizeof(dist)); dist[s]=0; HHeap now; now.pos=s,now.h=0; h.insert(now); while(h.siz){ int u=h.heap[1].pos; h.pop(); if(vis[u])continue; vis[u]=1; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(dist[d]>dist[u]+node[i].val){ dist[d]=dist[u]+node[i].val; now.pos=d,now.h=dist[d]; h.insert(now);//入堆 } } } } }D; ///////////////////////////////////// //////////////////////////////////////// //树链剖分//由于不想写取模,所以过不了板子 struct SLPF{ int n,m; struct Node{ int v; int next; }node[N<<1]; int cnt,head[N]; inline void addedge(int u,int v){ node[++cnt].v=v; node[cnt].next=head[u]; head[u]=cnt; } inline void add(int u,int v){ addedge(u,v); addedge(v,u); } int dep[N],siz[N],fa[N],son[N],top[N]; int T,dfn[N],real[N]; int a[N]; void dfs1(int u){ siz[u]=1; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(fa[u]!=d){ fa[d]=u; dep[d]=dep[u]+1; dfs1(d); siz[u]+=siz[d]; if(siz[d]>siz[son[u]])son[u]=d; } } } void dfs2(int u,int tp){ dfn[u]=++T; real[dfn[u]]=u; top[u]=tp; if(son[u])dfs2(son[u],tp); for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(fa[u]!=d&&son[u]!=d)dfs2(d,d); } } void changepath(int u,int v,int x){ while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]])swap(u,v); T2.update(1,dfn[top[v]],dfn[v],x); v=fa[top[v]]; } if(dep[u]>dep[v])swap(u,v); T2.update(1,dfn[u],dfn[v],x); } long long querypath(int u,int v){ long long ans=0; while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]])swap(u,v); ans+=T2.query(1,dfn[top[v]],dfn[v]); v=fa[top[v]]; } if(dep[u]>dep[v])swap(u,v); ans+=T2.query(1,dfn[u],dfn[v]); return ans; } void changetree(int u,int x){ int l=dfn[u]; int r=dfn[u]+siz[u]-1; T2.update(1,l,r,x); } long long querytree(int u){ int l=dfn[u]; int r=dfn[u]+siz[u]-1; return T2.query(1,l,r); } void init(){ n=Read(); register int i; for(i=1;i<=n;i++) a[i]=Read(); for(i=1;i<n;i++) add(Read(),Read()); dfs1(1); dfs2(1,1); for(i=1;i<=n;i++)T2.a[i]=a[real[i]]; T2.build(1,1,n); }//初始化 int lca(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]])swap(u,v); v=fa[top[v]]; } return dep[u]<dep[v]?u:v; } }slpf; ////////////////////////////////////// ////////////////////////////////////// //左偏树(小根堆) struct LPT{ struct Tree{ int len;//距离 int h;//优先级 int f;//父亲 int ls,rs;//左右儿子 }t[N]; int merge(int a,int b){ if(a==0||b==0)return a+b;//有一个为空 if(t[a].h>t[b].h)swap(a,b);//小根堆 t[a].rs=merge(t[a].rs,b); t[t[a].rs].f=a; if(t[t[a].rs].len>t[t[a].ls].len)swap(t[a].ls,t[a].rs); t[a].len=t[t[a].rs].len+1; return a; }//合并两个堆 void pop(int x){ t[t[x].ls].f=t[t[x].rs].f=0; merge(t[x].ls,t[x].rs);//合并左右儿子 }//堆顶出堆 int find(int x){ while(t[x].f)x=t[x].f; return x; }//查找堆顶 }H2; ////////////////////////////////// ///////////////////////////////// //线性基 struct Line{ long long b[65];//线性基数组 bool insert(long long val){ register int i; for(i=63;i>=0;i--){ if((val&((long long)1<<i))!=0){ if(b[i]==0){//最高位为该位的数还没有 b[i]=val; return 1; } val^=b[i]; } } return 0;//插入失败 }//插入val Line merge(const Line &a,const Line &b){ Line s=a; for(register int i=63;i>=0;i--){ if(b.b[i]){//把一个线性基暴力地插入另一个中 s.insert(b.b[i]); } } return s; }//合并两个线性基 bool find(long long val){ return !insert(val); }//val是否在线性基内 long long query_max(){ long long ans=0; for(int i=63;i>=0;i--){ if((ans^b[i])>ans)ans^=b[i]; } return ans; }//查询最大异或和 long long query_min(){ for(int i=0;i<=63;i++)if(b[i])return b[i]; return 0; }//查询最小异或和 long long query_maxn(long long x){ long long ans=x; for(int i=63;i>=0;i--){ if((ans^b[i])>ans)ans^=b[i]; } return ans; }//查询包含x的最大异或和 (x不在线性基内) long long query_minn(long long x){ long long ans=x; for(int i=0;i<=63;i++){ if((ans^b[i])<ans)ans^=b[i]; } return ans; }//查询包含x的最小异或和(x不在线性基内) }L; /////////////////////////////////////////// ////////////////////////////////////////// //字典树 const int len=1001010;//所有单词包含字母的总数 struct Tire{ int cnt;//字母数 int son[len][26];//以只有小写字母为例 bool end[len]; void insert(char s[]){ int now=0; int a; int l=strlen(s); for(int i=0;i<l;i++){ a=s[i]-'a'; if(son[now][a])now=son[now][a]; else son[now][a]=++cnt,now=cnt; } end[now]=1;//标记该单词出现了 }//插入单词 bool find(char s[]){ int now=0; int a; int l=strlen(s); for(int i=0;i<l;i++){ a=s[i]-'a'; if(son[now][a])now=son[now][a]; else return 0; } if(end[now])return 1; return 0; }//查找某个单词是否出现过 }; //////////////////////////////// //////////////////////////////// //(带修改)莫队 //由于涉及排序,好像不资瓷结构体 int cnt[mx]; int a[mx];//原数组 int ansk[mx];//答案 int cntq,cntc;//询问和修改的次数 int ans; int n; int now;//当前处理到了第几个询问 int st;//块的大小 int l,r;//当前询问的左右端点 inline void del(int x){ cnt[a[x]]--; if(cnt[a[x]]==0)ans--; } inline void add(int x){ cnt[a[x]]++; if(cnt[a[x]]==1)ans++; } struct Qu{//询问 int l,r;//每个询问左右端点 int pos;//每个询问位置 int pre;//每个询问最近的修改位置 }qu[mx]; struct C{//修改 int pos; int color; }c[mx]; bool cmp(Qu a,Qu b){ if(a.l/st!=b.l/st)return a.l/st<b.l/st; if(a.r/st!=b.r/st){ if((a.l/st)&1)return a.r<b.r; else return a.r>b.r; } return a.pre<b.pre; }//带修改莫队排序方式 //bool cmp(Qu a,Qu b){ // if(a.l/st!=b.l/st)return a.l<b.l; // if((a.l/st)&1)return a.r<b.r; // return a.r>b.r; //}//不带修改的莫队排序方式 void change(int i){//第i个询问需要的修改 if(qu[i].r>=c[now].pos&&qu[i].l<=c[now].pos){//本次修改会产生影响 if(--cnt[a[c[now].pos]]==0)ans--;//把该颜色的最后一个拿掉了 if(++cnt[c[now].color]==1)ans++;//第一次出现该颜色 } swap(a[c[now].pos],c[now].color); } int query(int i){//处理第i个询问 while(l<qu[i].l)del(l++); while(l>qu[i].l)add(--l); while(r<qu[i].r)add(++r); while(r>qu[i].r)del(r--);//不带修改的莫队只有前四排 while(now<qu[i].pre)change(++now); while(now>qu[i].pre)change(now--); return ans; } void init(){ //根据题目描述输入询问和修改 // st=n/sqrt(cntq*2/3);//不带修改的快的大小 st=exp((log(n)+log(cntq))/3);//带修改的块的大小 sort(qu+1,qu+1+cntq,cmp); for(int i=1;i<=cntq;i++)ansk[qu[i].pos]=query(i); } ///////////////////////////////////////////// ///////////////////////////////////////////// //tarjan(缩点与2-sat) struct Tarjan{ int n,m; int top,head[N]; struct Node{ int v; int next; }node[M]; inline void addedge(int u,int v){ node[++top].v=v; node[top].next=head[u]; head[u]=top; } int Belong[N];//每个点属于哪个强连通分量 int dfn[N],T,low[N]; int st[N];//栈 bool instack[N];//是否在栈中 int sttop;//栈顶 int taj;//强连通分量数 void dfs(int u){ dfn[u]=low[u]=++T; st[++sttop]=u; instack[u]=1; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(dfn[d]==0){ dfs(d); low[u]=min(low[u],low[d]); }else if(instack[d])low[u]=min(low[u],low[d]); } if(low[u]==dfn[u]){ int now; taj++; do{ now=st[sttop--]; instack[now]=0; Belong[now]=taj; //在此可以进行累加点权等操作 }while(now!=u); } } Node newnode[M]; int newtop; int newhead[N]; inline void newaddedge(int u,int v){ newnode[++newtop].v=v; newnode[newtop].next=newhead[u]; newhead[u]=newtop; } void suodian(){ for(int i=1;i<=n;i++)if(dfn[i]==0)dfs(i); for(int i=1;i<=n;i++){ int u=Belong[i]; for(int j=head[i];j;j=node[j].next){ int d=node[j].v; int v=Belong[d]; if(u!=v)newaddedge(u,v); } } } void Two_SAT(){ n=Read(),m=Read(); //[1,n]表示真,[n+1,2n]表示假 for(int i=1;i<=m;i++){ int a,fa,b,fb; a=Read(),fa=Read(),b=Read(),fb=Read(); addedge(a+(fa^1)*n,b+fb*n); addedge(b+(fb^1)*n,a+fa*n); } for(int i=1;i<=2*n;i++)if(dfn[i]==0)dfs(i); bool f=1; for(int i=1;i<=n;i++)if(Belong[i]==Belong[i+n])f=0; if(f)printf("POSSIBLE\n"); else printf("IMPOSSIBLE\n"); if(f)for(int i=1;i<=n;i++)printf("%d ",Belong[i]>Belong[i+n]); } }TJ; ////////////////////////////////// /////////////////////////////////// //splay struct Splay{ int son[mx][2],f[mx],siz[mx],key[mx],cnt[mx],root; int n,sz;//点数,当前有多少数在splay内 inline void update(int x){ if(x)siz[x]=cnt[x]+(son[x][0]?siz[son[x][0]]:0)+(son[x][1]?siz[son[x][1]]:0); } inline void clear(int x){siz[x]=key[x]=cnt[x]=son[x][0]=son[x][1]=f[x]=0;} inline bool get(int x){return son[f[x]][1]==x;} inline void rotate(int x){ int F=f[x],FF=f[F],WF=get(x),WFF=get(F); int other=son[x][WF^1]; f[x]=FF; if(F)son[FF][WFF]=x; f[F]=x; son[x][WF^1]=F; f[other]=F; son[F][WF]=other; update(F); update(x); } inline void splay(int x){ for(int F=f[x];(f[x]);rotate(x),F=f[x]){ if(f[F])rotate(get(x)==get(F)?F:x); } root=x; } void insert(int v){ if(root==0){ sz++; cnt[sz]=siz[sz]=1; son[sz][0]=son[sz][1]=f[sz]=0; key[sz]=v; root=sz; return; } int now=root,F=0; while(1){ if(key[now]==v){//已经插入过了 cnt[now]++; update(now); update(F); splay(now); return; } F=now; now=son[now][key[now]<v]; if(now==0){ ++sz; cnt[sz]=siz[sz]=1; son[sz][0]=son[sz][1]=0; f[sz]=F; son[F][key[F]<v]=sz; key[sz]=v; update(F); splay(sz); return; } } }//删除v int find(int v){ int ans=0,now=root; while(1){ if(key[now]>v)now=son[now][0]; else { ans+=(son[now][0]?siz[son[now][0]]:0); if(v==key[now]){ splay(now); return ans+1; } ans+=cnt[now]; now=son[now][1]; } } }//查v的排名 int findx(int x){ int now=root; while(1){ if(son[now][0]&&x<=siz[son[now][0]])now=son[now][0]; else{ int temp=(son[now][0]?siz[son[now][0]]:0)+cnt[now]; if(x<=temp)return key[now]; now=son[now][1]; x-=temp; } } }//查找排名为x的值 //注意查前驱之前要先插入v,查完之后要删除v inline int query_pre(){ int now=son[root][0]; while(son[now][1])now=son[now][1]; return now; }//查前驱 inline int query_aft(){ int now=son[root][1]; while(son[now][0])now=son[now][0]; return now; }//查后继 inline void del(int v){ find(v);//把v旋转到根 if(cnt[root]>1){//不止一个点 cnt[root]--; update(root); return; } if(son[root][0]==0&&son[root][1]==0){//只有根节点一个点 clear(root); root=0; return; } if(son[root][0]==0){//只有右子树 int oldroot=root; root=son[root][1]; f[root]=0; clear(oldroot); return; } if(son[root][1]==0){//只有左子树 int oldroot=root; root=son[root][0]; f[root]=0; clear(oldroot); return; } //有两个子树时: int newroot=query_pre(),oldroot=root;//用前驱做新根 splay(newroot);//把前驱旋转到根 f[son[oldroot][1]]=root;//经过旋转root==newroot son[root][1]=son[oldroot][1]; clear(oldroot); update(root); }//删除v }SPLAY; //////////////////////////////// //////////////////////////////// //LCT struct LCT{ int n,m; struct Lct{ int son[2]; int f;//父亲 bool t;//翻转标记 }lct[N]; #define swap(x,y) x^=y^=x^=y inline void pushdown(int x){ if(lct[x].t){ swap(lct[x].son[0],lct[x].son[1]); lct[lct[x].son[0]].t^=1; lct[lct[x].son[1]].t^=1; lct[x].t=0; } } inline void update(int x){ //视题目而定 } inline bool get(int x){return lct[lct[x].f].son[1]==x;} inline bool isroot(int x){return lct[lct[x].f].son[1]!=x&&lct[lct[x].f].son[0]!=x;} inline void rotate(int x){ int F=lct[x].f,FF=lct[F].f,WF=get(x),WFF=get(F); int other=lct[x].son[WF^1]; lct[x].f=FF; if(!isroot(F))lct[FF].son[WFF]=x; lct[other].f=F; lct[F].son[WF]=other; lct[x].son[WF^1]=F; lct[F].f=x; update(F); update(x); } int st[mx];//栈 inline void splay(int x){ int top=0,now=x; st[++top]=now; while(!isroot(now))now=lct[now].f,st[++top]=now; while(top)pushdown(st[top--]); for(int F=lct[x].f;!isroot(x);rotate(x),F=lct[x].f){ if(!isroot(F))rotate(get(x)==get(F)?F:x); } } inline void access(int x){//把x到根的路径改为实链 int pre=0; while(x){ splay(x); lct[x].son[1]=pre; pre=x; update(x); x=lct[x].f; } } inline void makeroot(int x){//把x改为根 access(x); splay(x); lct[x].t^=1; } inline int findroot(int x){//找到x的根 access(x); splay(x); pushdown(x); while(lct[x].son[0])x=lct[x].son[0];//根节点一定是最浅的 return x; } inline void spilt(int x,int y){//把x到y的路径放在一根实链上 makeroot(x); access(y); splay(y); } inline void link(int x,int y){//x与y加边 makeroot(x); if(findroot(y)!=x)//已经连通就不用加边了 lct[x].f=x;//findroot过程中已经把y旋转到根了 } inline void cut(int x,int y){//x与y删边 makeroot(x); if(findroot(y)!=x)return;//不连通就不用删边了 if(lct[x].f!=y||lct[y].son[0]!=x)return;//经过findroot,y成为了根 if(lct[x].son[1])return;//x的右儿子一定是比x深又比y浅的,即在他们之间,他们之间没有边 lct[x].f=0; lct[y].son[0]=0; update(y); } }LCT_Tree; ////////////////////////////////// ////////////////////////////////// //线性筛素数 struct Line_Prime{ int Prime[mx]; int o;//当前晒出了几个素数 bool chick[mx]; void solve(int n){//从1到n的素数 register int i,j; chick[1]=1; for(i=2;i<=n;i++){ if(chick[i]==0){ Prime[++o]=i; } for(j=1;j<=o;j++){ if(i*Prime[j]>n)break; chick[i*Prime[j]]=1; if(i%Prime[j]==0)break; } } } }LineP; ///////////////////////////////////// ////////////////////////////////////// //主席树 struct ZXTree{ int cnt;//现在有多少个点 int n,m;//n个数,m个询问 int q;//去重后后有多少个点 int l[mx<<5],r[mx<<5],root[mx],siz[mx<<5]; int a[mx],b[mx];//原数组,去重数组 void build(int &t,int ll,int rr){ t=++cnt; if(ll==rr)return; int mid=(ll+rr)>>1; build(l[t],ll,mid); build(r[t],mid+1,rr); }//建空树 int insert(int t,int ll,int rr,int p){ int o=++cnt; l[o]=l[t],r[o]=r[t],siz[o]=siz[t]+1; if(ll==rr)return o; int mid=(ll+rr)>>1; if(p<=mid)l[o]=insert(l[o],ll,mid,p); else r[o]=insert(r[o],mid+1,rr,p); return o; }//插入(去重后)第p大的新节点 int query(int u,int v,int ll,int rr,int k){ if(ll==rr)return ll; int mid=(ll+rr)>>1,x=siz[l[v]]-siz[l[u]]; if(x>k)return query(l[u],l[v],ll,mid,k); else return query(r[u],r[v],mid+1,rr,k-x); }//查询区间[u-1,v]第k小 int twopoint(int x){ int ll=1,rr=q; int mid; while(1){ mid=(ll+rr)>>1; if(b[mid]==x)return mid; if(b[mid]>x)rr=mid-1; else ll=mid+1; } }//二分出x是去重后第几大(用于插入前的预处理) void init(){ register int i; n=Read(),m=Read(); for(i=1;i<=n;i++)a[i]=Read(),b[i]=a[i]; sort(b+1,b+1+n); q=unique(b+1,b+1+n)-b-1;//去重后一共多少种数 build(r[0],1,q); for(i=1;i<=n;i++){ //嫌麻烦不想手写二分可以调用stl //p=lower_bound(b+1,b+1+q,a[i])-b; root[i]=insert(root[i-1],1,q,twopoint(a[i])); } int ll,rr,k; for(i=1;i<=m;i++){ ll=Read(),rr=Read(),k=Read(); printf("%d\n",b[query(root[ll-1],root[rr],1,q,k)]); } } }; //////////////////////////////// /////////////////////////////// //最小费用最大流(DInic) struct MINcostMAXflow{ int n,m,s,t; int maxflow,cost; int top; int head[N]; void init(){top=1;} struct Node{ int v; int val; int next; int w; }node[M]; inline void addedge(int u,int v,int val,int w){ node[++top].v=v; node[top].next=head[u]; node[top].w=w; node[top].val=val; head[u]=top; } inline void add(int u,int v,int val,int w){ addedge(u,v,val,w); addedge(v,u,0,-w); } int inque[N],dist[N],vis[N]; int cur[N];//当前弧 bool spfa(){ for(int i=1;i<=t;i++)cur[i]=head[i],dist[i]=inf; queue<int>q; q.push(s); dist[s]=0; while(!q.empty()){ int u=q.front(); q.pop(); inque[u]=0; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if(dist[d]>dist[u]+node[i].w){ dist[d]=dist[u]+node[i].w; if(!inque[d]){ q.push(d); inque[d]=1; } } } } return dist[t]!=inf; } int dfs(int u,int flow){ if(u==t){ maxflow+=flow; return flow; } int used=0; vis[u]=1; for(int i=head[u];i;i=node[i].next){ int d=node[i].v; if((vis[d]==0||d==t)&&dist[d]==dist[u]+node[i].w){ int mi=dfs(d,min(node[i].val,flow-used)); if(mi){ node[i].val-=mi; node[i^1].val+=mi; cost+=node[i].w*mi; used+=mi; if(used==flow)break; } } } return used; } void Dinic(){ while(spfa()){ vis[t]=1; while(vis[t]){ memset(vis,0,sizeof(vis)); dfs(s,inf); } } } }; //////////////////////////////// /////////////////////////////////// //并查集 struct BCJ{ int set[mx]; int n; void init(){ for(int i=1;i<=n;i++)set[i]=i; } int find(int x){ return set[x]==x?x:set[x]=find(set[x]); } void merge(int x,int y){ int sx=find(x),sy=find(y); if(sx==sy)return; if(sx>sy)swap(sx,sy); set[sy]=sx; } }; ///////////////////////////////// //////////////////////////////// //floyd struct Floyd{ int go[1010][1010]; int n; void solve(){ int i,j,k; for(k=1;k<=n;k++){ for(j=1;j<=n;j++){ for(i=1;i<=n;i++){ go[i][j]=min(go[i][j],go[i][k]+go[k][j]); } } } } }; //////////////////////////////////////// //////////////////////////////////////// //vector实现平衡树 struct VSplay{ /*一些关于vector的函数 定义:vector<int>a; 需<vector>头文件 访问元素:a[x] 取出a中的第(x+1)个数(下标从0开始 O(1) a.begin():返回起始元素的迭代器 O(1) a.end():返回终止元素的迭代器 O(1) a.insert(a.begin()+pos,x):在第pos个数后面插入x O(n) a.erase(a.begin()+pos):删除pos位置的数 pos之后的数自动补齐 O(n) lower_bound(a.begin(),a.end(),x)返回第一个大于等于x的位置的迭代器 O(logn) upper_bound(a.begin(),a.end(),x)返回第一个大于x的位置的迭代器(x的后继或x) O(logn) *it:取出迭代器it中的值*/ vector<int>v; void insert(int x){//插入x v.insert(upper_bound(v.begin(),v.end(),x),x); } void del(int x){//删除x v.erase(lower_bound(v.begin(),v.end(),x)); } int find_kth(int x){//查询x的排名 return lower_bound(v.begin(),v.end(),x)-v.begin()+1; } int find_val(int x){//查询排名为x的数 return v[x-1]; } int find_pre(int x){//查前驱 return *--lower_bound(v.begin(),v.end(),x); } int find_aft(int x){//查后继 return *upper_bound(v.begin(),v.end(),x); } }; /////////////////////////////////////////// ////////////////////////////////////////////// //高精度 struct Bign{ int len,s[mx];; Bign(){len=1,memset(s,0,sizeof(s));} Bign(int num){*this=num;} Bign(const char *num){*this=num;} Bign operator = (const int num){ char st[mx]; sprintf(st,"%d",num); return *this=st; } Bign operator = (const char *num){ len=strlen(num); for(int i=0;i<len;i++)s[i]=num[len-i-1]-'0'; return *this; } void clean(){while(len&&s[len-1]==0)len--;} Bign operator + (const Bign &x){ Bign c; int l=max(len,x.len); for(int i=0;i<l;i++){ c.s[i]+=s[i]+x.s[i]; c.s[i+1]+=c.s[i]/10; c.s[i]%=10; } c.len=l+1; c.clean(); return c; } Bign operator - (const Bign &x){ Bign c=*this; int l=max(len,x.len); for(int i=0;i<l;i++){ c.s[i]-=x.s[i]; if(c.s[i]<0){ c.s[i+1]--; c.s[i]+=10; } } c.clean(); return c; } Bign operator * (const Bign &b){ Bign c; for(int i=0;i<len;i++){ for(int j=0;j<b.len;j++){ c.s[i+j]+=s[i]*b.s[j]; c.s[i+j+1]+=c.s[i+j]/10; c.s[i+j]%10; } } c.len=len+b.len+1; c.clean(); return c; } bool operator > (const Bign &b){ if(len!=b.len)return len>b.len; for(int i=len-1;i>=0;i--){ if(s[i]!=b.s[i])return s[i]>b.s[i]; } return 0;//相等 } string str() const{ string re=""; for(int i=0;i<len;i++)re=(char)(s[i]+'0')+re; return re; } }; istream &operator >> (istream &in,Bign &x){ string s; cin>>s; x=s.c_str(); return in; } ostream &operator << (ostream &out,const Bign &x){ out<<x.str(); return out; } //////////////////////////// //////////////////////////// //矩阵快速幂 const int mod=(1e9)+7;//常见模数 struct MatMul{ struct Mat{ long long mat[101][101]; int n,m;//n行m列的矩阵 Mat(){memset(mat,0,sizeof(mat));n=m=0;} }; int n; Mat e; void init(){for(int i=0;i<=n;i++)e.mat[i][i]=1;}//预处理出单位矩阵 Mat Mul(Mat x,Mat y){//x与y相乘 register int i,j,k1; if(x.m!=y.n)return e;//必须满足能相乘的条件 Mat out; int n=x.n; int k=x.m; int m=y.m; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ for(k1=1;k1<=k;k1++){ out.mat[i][j]=(x.mat[i][k1]*y.mat[k1][j]+out.mat[i][j])%mod; } } } return out; } Mat pow(Mat x,long long k){//x矩阵的k次方 Mat ans=e; Mat base=x; while(k){ if(k&1)ans=Mul(ans,base); base=Mul(base,base); k>>=1; } return ans; } }; ////////////////////////// ////////////////////////// //背包 struct BackPack{ int dp[101010];//滚动数组 int n,W;//物品总数,总重量 int val[101010];//每个物品的价值 int w[101010];//每个物品的重量 void solve_01(){//01背包 int i,j; for(i=0;i<=n;i++){ for(j=W;j>=w[i];j--){//倒序循环防止多取 dp[j]=max(dp[j],dp[j-w[i]]+val[i]); } } printf("%d",dp[W]); } void solve_CM(){//完全背包 int i,j; for(i=0;i<=n;i++){ for(j=w[i];j<=W;j++){//正序循环可以多取 dp[j]=max(dp[j],dp[j-w[i]]+val[i]); } } printf("%d",dp[W]); } }; //////////////////////////////// /////////////////////////////// //扩展欧几里得 struct EXGCD{ void exgcd(int a,int b,int &d,int &x,int &y){ if(!b){ d=a;x=1;y=0; } else{ exgcd(b,a%b,d,y,x);//输入时要保证a>b否则会死循环 y-=x*(a/b); } }//求解ax+by==gcd(a,b),d为最大公因数,x,y为对应系数 }; //////////////////////////// //////////////////////////// //大概复习完了吧 int main(){ int noip_2018_score=0; while(noip_2018_score<=600)noip_2018_score++; printf("Your will AK noip 2018 TG"); int noip_2018_rp=0; while(1)noip_2018_rp++; return 0; } ``` 学OI以来打过最长的代码(第一个比无限之环还长的代码)