>w<
Windows对拍:
1 @echo off 2 3 set paht=C:WindowsSystem32 4 5 :loop 6 7 data.exe 8 ddd.exe 9 pai.exe 10 11 fc ddd.out pai.out 12 13 if not errorlevel 1 goto loop 14 15 pause 16 17 goto loop
gvim配置:
set ts=4 set sw=4 set smarttab set number color desert syntax on set cindent set guifont=Consolas:h16 imap ee <Esc>:w<CR>
一行gcd:
1 LL gcd(LL x,LL y){ return (y ? gcd(y,x%y) : x);}
线性基(带求交):
1 struct bss{ 2 int b[32]; 3 bss(){ 4 for(int i=0;i<=31;++i) b[i]=0; 5 } 6 bss(int x[]){ 7 for(int i=0;i<=31;++i) b[i]=x[i]; 8 } 9 void ist(int x){ 10 for(int i=31;i>=0;--i)if(x>>i&1){ 11 if(!b[i]){ 12 b[i]=x; 13 return ; 14 } 15 x^=b[i]; 16 } 17 } 18 bool chck(int x){ 19 for(int i=31;i>=0;--i)if(x>>i&1) 20 x^=b[i]; 21 return !x; 22 } 23 }; 24 bss mg(bss x,bss y){ 25 bss bwl=x,nb=x,z; 26 for(int i=0;i<=31;++i)if(y.b[i]){ 27 int tma=0,tmb=y.b[i]; 28 for(int j=i;j>=0;--j)if(tmb>>j&1){ 29 if(bwl.b[j]){ 30 tmb^=bwl.b[j],tma^=nb.b[j]; 31 if(!tmb){ 32 z.b[i]=tma; 33 break; 34 } 35 } 36 else{ 37 bwl.b[j]=tmb; 38 nb.b[j]=tma; 39 break; 40 } 41 } 42 } 43 return z; 44 }
(小根)堆:
1 int hp[110000],sz=0; 2 void ist(int z){ 3 int x; hp[x=(++sz)]=z; 4 while(x!=1 && hp[x]<hp[x>>1]) swap(hp[x],hp[x>>1]),x>>=1; 5 } 6 void pp(){ 7 hp[1]=hp[sz--]; 8 int x=1,mnid=1; 9 for(;;){ 10 mnid=x; 11 if((x<<1)<=sz && hp[x<<1]<hp[mnid]) mnid=(x<<1); 12 if((x<<1|1)<=sz && hp[x<<1|1]<hp[mnid]) mnid=(x<<1|1); 13 if(mnid==x) break; 14 swap(hp[mnid],hp[x]); 15 x=mnid; 16 } 17 }
后缀数组(下标从1开始):
1 char s[1100000]; int n=0; 2 int rk[1100000],hght[1100000]; 3 int cnt[220],cntrk[1100000]; 4 int rk1[1100000],rk2[1100000]; 5 int sa[1100000],tmpsa[1100000]; 6 void gtsffxrk(){ 7 memset(cnt,0,sizeof(cnt)); 8 for(int i=1;i<=n;++i) ++cnt[(int)s[i]]; 9 for(int i=1;i<=210;++i) cnt[i]+=cnt[i-1]; 10 for(int i=1;i<=n;++i) rk[i]=cnt[(int)s[i]]; 11 for(int l=1;l<n;l<<=1){ 12 for(int i=1;i<=n;++i) rk1[i]=rk[i],rk2[i]=(i+l>n ? 0 : rk[i+l]); 13 fill(cntrk+1,cntrk+1+n,0); 14 //每一步都必须fill,因为cntrk求了前缀和,cntrk--并不会把所有cntrk都减成0 15 for(int i=1;i<=n;++i) ++cntrk[rk2[i]]; 16 for(int i=1;i<=n;++i) cntrk[i]+=cntrk[i-1]; 17 //i从1开始,注意因为空字符的存在所以还是有0rank的 18 for(int i=n;i>=1;--i) tmpsa[cntrk[rk2[i]]--]=i; 19 fill(cntrk+1,cntrk+1+n,0); 20 for(int i=1;i<=n;++i) ++cntrk[rk1[i]]; 21 for(int i=1;i<=n;++i) cntrk[i]+=cntrk[i-1]; 22 for(int i=n;i>=1;--i) sa[cntrk[rk1[tmpsa[i]]]--]=tmpsa[i]; 23 rk[sa[1]]=1; 24 //如果rank从0开始,对于全部一样的串如"aaaa"会出问题,把最小的rank和空字符混淆 25 bool flg=true; 26 for(int i=2;i<=n;++i){ 27 rk[sa[i]]=rk[sa[i-1]]; 28 rk[sa[i]]+=(rk1[sa[i]]!=rk1[sa[i-1]] || rk2[sa[i]]!=rk2[sa[i-1]]); 29 if(rk1[sa[i]]==rk1[sa[i]] || rk2[sa[i]]==rk2[sa[i]]) flg=false; 30 //if(rk[sa[i]]==rk[sa[i-1]]) flg=false; 31 } 32 if(flg) break; 33 } 34 } 35 void gthght(){ 36 int l=0; 37 for(int i=1;i<=n;++i)if(rk[i]>1){ 38 int j=sa[rk[i]-1]; 39 while(i+l<=n && j+l<=n && s[i+l]==s[j+l]) ++l; 40 //i+l表示的实际上是长度为i+l-1的串的最后一个字符 41 hght[rk[i]]=l; 42 l-=(l>0); 43 } 44 }
dinic(当前弧优化):
1 const LL oo=1000000000000007; 2 struct edg{int y,nxt; LL v;}e[11000]; int lk[110],ltp=1; 3 //注意两倍边数组 4 void ist(int x,int y,int z){ 5 e[++ltp]=(edg){y,lk[x],z}; lk[x]=ltp; 6 //注意结构体内变量顺序 7 e[++ltp]=(edg){x,lk[y],0}; lk[y]=ltp; 8 //因为要用i^1表示反向边所以边的标号从2开始 9 } 10 int n,m; int s,t; 11 int lvl[110]; 12 int q[110],hd=0; 13 int crt[110]; 14 bool gtlvl(){ 15 memset(lvl,0,sizeof(lvl)); 16 lvl[q[hd=1]=s]=1; 17 for(int k=1;k<=hd;++k){ 18 crt[q[k]]=lk[q[k]]; 19 //注意crt要初始化 20 for(int i=lk[q[k]];i;i=e[i].nxt)if(e[i].v && !lvl[e[i].y]){ 21 q[++hd]=e[i].y; 22 lvl[e[i].y]=lvl[q[k]]+1; 23 } 24 } 25 return lvl[t]; 26 } 27 LL mxflw(int x,LL y){ 28 if(x==t) return y; 29 LL bwl=0,flw=0; 30 for(int i=crt[x];i && bwl<y;i=e[i].nxt)if(lvl[e[i].y]==lvl[x]+1 && e[i].v) 31 //注意i=crt[x] 32 if((flw=mxflw(e[i].y,min(y-bwl,e[i].v)))){ 33 //注意y和v,易错点 34 e[i].v-=flw,e[i^1].v+=flw; 35 bwl+=flw; 36 if(!e[i].v) crt[x]=e[i].nxt; 37 //唯一的改动,很好写 38 //注意必须某条边跑满才能换下一个,否则会负优化 39 } 40 if(!bwl) lvl[x]=0; 41 return bwl; 42 } 43 LL dnc(){ 44 LL bwl=0,flw=0; 45 while(gtlvl())while((flw=mxflw(s,oo))) bwl+=flw; 46 return bwl; 47 }
平衡树treap(假删除):
1 int c[110000][2],v[110000],u[110000],sz[110000],ntp=0,rt=0; 2 int nb[110000],fth[110000]; 3 void rtt(int x,bool mk){ 4 int l=mk^1,r=mk,y=fth[x],z=fth[fth[x]]; 5 //l和r的选取必须看以左旋还是右旋为例 6 if(c[x][r]) fth[c[x][r]]=y; 7 //c[x][r]可能为空 8 fth[y]=x,fth[x]=z; 9 c[y][l]=c[x][r],c[x][r]=y; 10 //x肯定有爸爸,没有爸爸旋个毛线 11 if(z) c[z][c[z][1]==y]=x; //注意这里不是l和r 12 //总共涉及到3条边,所以共有6个赋值 13 sz[x]=sz[y],sz[y]=sz[c[y][0]]+sz[c[y][1]]+nb[y]; 14 if(y==rt) rt=x; 15 //注意rt 16 } 17 void mt(int x){ 18 while(fth[x] && u[x]<u[fth[x]]) rtt(x,c[fth[x]][0]==x); 19 } 20 void ist(int x,int y,int z){ 21 if(!x){ 22 x=++ntp; 23 if(!rt) rt=x; 24 v[x]=z,u[x]=rand(); 25 sz[x]=1,nb[x]=1; 26 fth[x]=y; if(y) c[y][z>v[y]]=x; 27 //x肯定要设置爸爸,但爸爸可能为空,细节要考虑到 28 c[x][0]=0,c[x][1]=0; 29 mt(x); 30 return ; 31 } 32 ++sz[x]; 33 if(z==v[x]) ++nb[x]; 34 else ist(c[x][z>v[x]],x,z); 35 } 36 void dlt(int x,int z){ 37 if(!x) return ; 38 --sz[x]; 39 if(z==v[x]) --nb[x]; 40 else dlt(c[x][z>v[x]],z); 41 return ; 42 } 43 int gtrk(int x,int z){ 44 if(!x) return -1; 45 if(z==v[x]) return sz[c[x][0]]+1; 46 else return gtrk(c[x][z>v[x]],z)+(z>v[x] ? sz[c[x][0]]+nb[x] : 0); 47 } 48 int slct(int x,int z){ 49 if(!x) return -1; 50 if(z<=sz[c[x][0]]) return slct(c[x][0],z); 51 //注意别写混成gtrk 52 else if(z-sz[c[x][0]]<=nb[x]) return v[x]; 53 else return slct(c[x][1],z-sz[c[x][0]]-nb[x]); 54 } 55 int gtcsctv(int x,int z,bool mk){ 56 int l=mk,r=mk^1; 57 //前驱后继也是镜像操作 58 while(v[x]!=z){ 59 if(!c[x][z>v[x]]){ 60 ist(rt,0,z),dlt(rt,z); 61 //注意一定要从rt开始插入和删除,如果从x开始会有很多问题 62 //比如被旋走,比如插入途径加的sz没有删干净 63 x=ntp; 64 } 65 //保证第一遍查找的时候不会找到假节点 66 else x=c[x][z>v[x]]; 67 //注意一定要else,否则新插入的点可能会被maintain跑 68 } 69 if(!c[x][l]){ 70 while(fth[x] && c[fth[x]][r]!=x) x=fth[x]; 71 if(!fth[x]) return -1; 72 x=fth[x]; 73 } 74 else{ 75 //注意这里是else,如果开始爸爸就不用再找儿子了 76 x=c[x][l]; 77 while(c[x][r]) x=c[x][r]; 78 } 79 if(nb[x]) return v[x]; 80 else return gtcsctv(x,v[x],mk); 81 //如果偷懒不删除则要注意找到的点是否已经没有数了 82 //感觉这样容易反复查找被卡,但是没有证据 83 }
cdq分治(三维数星星小于等于版):
1 void cdq(int l,int r,int cl,int cr){ 2 if(l>=r) return ; 3 if(cl==cr){ 4 for(int i=l;i<=r;++i){ 5 int tmp=1; 6 //注意这里对于全等点的处理 7 while(i+tmp<=r && a[i+tmp].a==a[i].a && a[i+tmp].c==a[i].c) ++tmp; 8 //i+tmp表示的实际上是长度为tmp+1的区间的右端点 9 for(int j=0;j<tmp;++j) a[i+j].ans+=tmp-1+qry(a[i].c); 10 //别忘了qry 11 mdf(a[i].c,tmp); 12 i+=tmp-1; 13 //注意是+tmp-1不是=也不是+tmp 14 } 15 for(int i=l;i<=r;++i) mdf(a[i].c,-1); 16 return ; 17 } 18 int md=(cl+cr)>>1; 19 int cnt1=0,cnt2=0; 20 for(int i=l;i<=r;++i){ 21 if(a[i].b<=md){ 22 mdf(a[i].c,1); 23 ++cnt1; 24 } 25 else{ 26 a[i].ans+=qry(a[i].c); 27 ++cnt2; 28 } 29 } 30 for(int i=l;i<=r;++i)if(a[i].b<=md) mdf(a[i].c,-1); 31 cnt1+=l; cnt2+=cnt1; 32 for(int i=r;i>=l;--i) q[--(a[i].b<=md ? cnt1 : cnt2)]=a[i]; 33 for(int i=l;i<=r;++i) a[i]=q[i]; 34 cdq(l,cnt2-1,cl,md),cdq(cnt2,r,md+1,cr); 35 } 36 bool cmp(nds x,nds y){ return (x.a==y.a ? (x.b==y.b ? x.c<y.c : x.b<y.b) : x.a<y.a);} 37 //这个顺序很重要
树状数组:
1 inline int lbt(int x){ return x&-x;} 2 //v[x]统计的是[x-lowbit(x)+1,x]的所有数 3 void mdf(int x,int z){ while(x<=m){ v[x]+=z; x+=lbt(x);}} 4 //+lowbit的目的不是把1变成0,而是把0变成1 5 int qry(int x){ 6 int bwl=0; 7 while(x){ bwl+=v[x]; x-=lbt(x);} 8 return bwl; 9 }
tarjan求割点(无向图):
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int rd(){int z=0,mk=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')mk=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 10 return z*mk; 11 } 12 struct edg{int y,nxt;}e[210000]; int lk[21000],ltp=0; 13 void ist(int x,int y){ 14 e[++ltp]=(edg){y,lk[x]}; lk[x]=ltp; 15 e[++ltp]=(edg){x,lk[y]}; lk[y]=ltp; 16 } 17 int n,m; 18 int dfn[21000],low[21000],dft=0; 19 int aq[21000],atp=0; 20 void tj(int x,int y){ 21 dfn[x]=++dft; low[x]=dfn[x]; 22 bool flg1=false,flg2=false; 23 for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=y){ 24 if(!dfn[e[i].y]){ 25 tj(e[i].y,x); 26 if(!y && flg1) flg2=true; 27 //注意顺序!放到后边就错了 28 if(low[e[i].y]>=dfn[x]) flg1=true; 29 low[x]=min(low[x],low[e[i].y]); 30 } 31 else low[x]=min(low[x],dfn[e[i].y]); 32 //注意这里是dfn 33 } 34 if(y && flg1) aq[++atp]=x; 35 if(!y && flg2) aq[++atp]=x; 36 } 37 void prvs(){ 38 for(int i=1;i<=n;++i) dfn[i]=0,low[i]=0; 39 dft=0; 40 atp=0; 41 } 42 int main(){ 43 //freopen("ddd.in","r",stdin); 44 cin>>n>>m; prvs(); 45 int l,r; 46 while(m --> 0){ l=rd(),r=rd(); ist(l,r);} 47 for(int i=1;i<=n;++i)if(!dfn[i]) tj(i,0); 48 sort(aq+1,aq+atp+1); 49 printf("%d ",atp); 50 for(int i=1;i<=atp;++i) printf("%d ",aq[i]); 51 printf(" "); 52 return 0; 53 }
手写堆排序:
1 nds a[110000]; 2 bool cmp(nds &x,nds &y){ return x.c<y.c;} 3 void st(){ 4 for(int i=1;i<=m;++i) 5 for(int j=i;j>1 && b[j].c<b[j>>1].c;j>>=1) swap(b[j],b[j>>1]); 6 int sz=m; 7 for(int i=1;i<=m;++i){ 8 a[i]=b[1]; 9 swap(b[1],b[sz--]); 10 for(int j=1;j<=sz;){ 11 int k=j; 12 if((j<<1)<=sz && b[j<<1].c<b[k].c) k=(j<<1); 13 if((j<<1|1)<=sz && b[j<<1|1].c<b[k].c) k=(j<<1|1); 14 if(k==j) break; 15 swap(b[j],b[k]); 16 j=k; 17 } 18 } 19 for(int i=1;i<=m;++i) b[i]=a[i]; 20 }
费用流:
1 const int oo=1000000007; 2 struct edg{int nxt,y,v,u;}e[31000]; int lk[4100],ltp=1; 3 void ist(int x,int y,int z,int w){ 4 e[++ltp]=(edg){lk[x],y,z,w}; lk[x]=ltp; 5 e[++ltp]=(edg){lk[y],x,0,-w}; lk[y]=ltp; 6 } 7 int n,m,ft,st,fc,sc,a[2100]; 8 int s,t; 9 int dstc[4100]; 10 int q[41000],hd=0; bool vstd[4100]; 11 int lst[4100],lse[4100]; 12 bool spfa(){ 13 for(int i=1;i<=t;++i){ 14 vstd[i]=false; 15 dstc[i]=oo; 16 } 17 dstc[q[hd=1]=s]=0; 18 for(int k=1;k<=hd;++k){ 19 for(int i=lk[q[k]];i;i=e[i].nxt) 20 if(e[i].v && dstc[q[k]]+e[i].u<dstc[e[i].y]){ 21 dstc[e[i].y]=dstc[q[k]]+e[i].u; 22 lst[e[i].y]=q[k],lse[e[i].y]=i; 23 if(!vstd[e[i].y]){ 24 q[++hd]=e[i].y; 25 vstd[e[i].y]=true; 26 } 27 } 28 vstd[q[k]]=false; 29 } 30 //return dstc[t]; 注意不是判断dstc[t]不为0 31 return dstc[t]!=oo; 32 } 33 LL cstflw(){ 34 LL bwl=0; 35 while(spfa()){ 36 int flw=oo; 37 for(int i=t;i!=s;i=lst[i]) 38 flw=min(flw,e[lse[i]].v); 39 for(int i=t;i!=s;i=lst[i]){ 40 bwl+=flw*e[lse[i]].u; 41 e[lse[i]].v-=flw,e[lse[i]^1].v+=flw; 42 //cout<<i<<"<-"; 43 } 44 //cout<<endl; 45 } 46 return bwl; 47 }
线筛求质数:
1 int s[1100000]; 2 void gtprm(){ 3 for(int i=2;i<=m;++i){ 4 if(!flg[i]) prm[++prt]=i; 5 for(int j=1;j<=prt && i*prm[j]<=m;++j){ 6 flg[i*prm[j]]=true; 7 if(!(i%prm[j])) break; 8 } 9 } 10 }
splay(文艺平衡树,区间反转):
1 struct nds{ 2 int f,c[2]; 3 int v,s; 4 int d; 5 nds(){ 6 f=0,c[0]=0,c[1]=0; 7 v=0,s=0; 8 d=0; 9 } 10 }t[110000]; int tt=0,rt=0; 11 int n,m,a[110000]; 12 //pushup 13 void psu(int x){ 14 t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+1; 15 } 16 //pushdown 17 void psd(int x){ 18 if(!t[x].d) return ; 19 int l=t[x].c[0],r=t[x].c[1]; 20 t[l].d^=1,t[r].d^=1; 21 t[x].d=0; 22 swap(t[x].c[0],t[x].c[1]); 23 } 24 //rotate 25 void rtt(int x,int w){ 26 int y=t[x].f; 27 int z=t[y].f; 28 int r=(t[y].c[0]==x); 29 int l=(r^1); 30 if(z) t[z].c[t[z].c[1]==y]=x; 31 else rt=x; 32 t[t[x].c[r]].f=y,t[y].f=x,t[x].f=z; 33 t[y].c[l]=t[x].c[r],t[x].c[r]=y; 34 psu(y),psu(x); 35 } 36 //splay 37 void spl(int x,int w){ 38 int y,z; 39 while(t[x].f!=w){ 40 y=t[x].f; 41 z=t[y].f; 42 if(t[y].f!=w) rtt(((t[y].c[0]==x)^(t[z].c[0]==y)) ? x : y,w); 43 rtt(x,w); 44 } 45 } 46 //select 47 int slc(int x,int w){ 48 if(!x) return 0; 49 psd(x); //注意pushdown 50 if(w<=t[t[x].c[0]].s) return slc(t[x].c[0],w); 51 else if(w==t[t[x].c[0]].s+1) return x; 52 else return slc(t[x].c[1],w-t[t[x].c[0]].s-1); 53 } 54 //estabilsh 55 int est(int l,int r,int y){ 56 if(l>r) return 0; 57 int md=(l+r)>>1; 58 int x=++tt; 59 t[x].f=y,t[x].c[0]=0,t[x].c[1]=0; 60 t[x].v=a[md],t[x].s=1; 61 t[x].d=0; 62 if(md-1>=l) t[x].c[0]=est(l,md-1,x); 63 if(r>=md+1) t[x].c[1]=est(md+1,r,x); 64 psu(x); 65 return x; 66 } 67 void iod(int x){ 68 if(!x) return ; 69 psd(x); 70 if(t[x].c[0]) iod(t[x].c[0]); 71 printf("%d ",t[x].v); 72 if(t[x].c[1]) iod(t[x].c[1]); 73 } 74 int main(){ 75 cin>>n>>m; 76 for(int i=1;i<=n;++i) a[i]=i; 77 rt=est(1,n,0); 78 int l,r; 79 while(m --> 0){ 80 scanf("%d%d",&l,&r); 81 if(l==r) continue; //注意特判 82 //否则splay(y,x)出错 83 int x=slc(rt,l),y=slc(rt,r); 84 spl(x,0),spl(y,x); 85 swap(t[x].v,t[y].v); //画图即懂 86 t[t[y].c[0]].d^=1; //注意不是t[r] 87 } 88 iod(rt); 89 return 0; 90 }
堆优化的Dijkstra:
1 const int oo=1000000007; 2 struct edg{int nxt,y,v;}e[410000]; int lk[110000],ltp=0; 3 void ist(int x,int y,int z){ 4 e[++ltp]=(edg){lk[x],y,z}; lk[x]=ltp; 5 e[++ltp]=(edg){lk[y],x,z}; lk[y]=ltp; 6 } 7 struct nds{ 8 int x,y; 9 bool operator<(nds z){ return y<z.y;} 10 }hp[410000]; int sz=0; //堆大小为边数 11 void psh(nds z){ 12 hp[++sz]=z; 13 for(int i=sz;i!=1 && hp[i]<hp[i>>1];i>>=1) swap(hp[i],hp[i>>1]); 14 } 15 void pp(){ 16 hp[1]=hp[sz--]; 17 int x=1,mn=1; 18 for(;;){ 19 mn=x; 20 if((x<<1)<=sz && hp[x<<1]<hp[mn]) mn=(x<<1); 21 if((x<<1|1)<=sz && hp[x<<1|1]<hp[mn]) mn=(x<<1|1); 22 if(mn==x) break; 23 swap(hp[mn],hp[x]); 24 x=mn; 25 } 26 } 27 int n,m; 28 int dstc[110000],lst[110000]; 29 void dij(int x){ 30 sz=0; 31 for(int i=1;i<=n;++i) dstc[i]=oo; 32 dstc[x]=0; 33 psh((nds){x,0}); 34 while(sz){ 35 while(sz && hp[1].y>dstc[hp[1].x]) pp(); 36 //最大队列长度为边数,因为每个边至多松弛一次 37 //每松弛一次加一个点入队 38 if(!sz) break; 39 x=hp[1].x; dstc[x]=hp[1].y; //x复用警告 40 pp(); 41 for(int i=lk[x];i;i=e[i].nxt)if(dstc[x]+e[i].v<dstc[e[i].y]){ 42 dstc[e[i].y]=dstc[x]+e[i].v; 43 psh((nds){e[i].y,dstc[e[i].y]}); 44 lst[e[i].y]=x; 45 } 46 } 47 }
圆方树:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 struct edg{int nxt,y;}e[810000]; int lk[210000],lhd=0; //注意原图也要双倍 5 void ist(int x,int y){ 6 e[++lhd]=(edg){lk[x],y}; lk[x]=lhd; 7 e[++lhd]=(edg){lk[y],x}; lk[y]=lhd; 8 } 9 edg g[810000]; int gk[210000],ghd=0; 10 void gst(int x,int y){ 11 g[++ghd]=(edg){gk[x],y}; gk[x]=ghd; 12 g[++ghd]=(edg){gk[y],x}; gk[y]=ghd; 13 } 14 int n,m,o; 15 int dfn[210000],low[210000],dfc=0; //注意开双倍,因为有两种点 16 int q[210000],hd; 17 int cnt=0; 18 int s[210000]; 19 int f[210000],ft=0; 20 int ast[210000][20]; 21 int dp[210000]; 22 void tj(int x){ 23 dfn[x]=++dfc; 24 low[x]=dfc; 25 q[++hd]=x; 26 for(int i=lk[x];i;i=e[i].nxt){ 27 if(!dfn[e[i].y]){ 28 tj(e[i].y); 29 low[x]=min(low[x],low[e[i].y]); 30 if(low[e[i].y]==dfn[x]){ //找到一个点双 31 ++cnt; //增加方点个数 32 for(int j=0;j!=e[i].y;--hd){ //将点双中除了u的点退栈,并在圆方树中连边 33 j=q[hd]; 34 gst(cnt,j); 35 } 36 gst(cnt,x); //u自身也要连边,但不退栈 37 } 38 } 39 else{ 40 low[x]=min(low[x],dfn[e[i].y]); 41 } 42 } 43 } 44 void gte(){ //从临时图g转移到常用图e 45 for(int i=1;i<=cnt;++i) lk[i]=gk[i]; 46 for(int i=1;i<=ghd;++i) e[i]=g[i]; 47 lhd=ghd; 48 } 49 void dfs(int x,int y){ 50 f[x]=ft; 51 s[x]=s[y]; 52 if(x<=n) s[x]++; 53 dp[x]=dp[y]+1; 54 ast[x][0]=y; 55 for(int i=1;(1<<i)<=dp[x];++i) ast[x][i]=ast[ast[x][i-1]][i-1]; 56 for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=y){ 57 dfs(e[i].y,x); 58 } 59 } 60 int lca(int x,int y){ 61 if(dp[x]<dp[y]) swap(x,y); 62 int tmp=dp[x]-dp[y]; 63 for(int i=0;i<=19;++i)if((1<<i)&tmp) x=ast[x][i]; 64 for(int i=16;i>=0;--i)if(ast[x][i]!=ast[y][i]){ 65 x=ast[x][i]; 66 y=ast[y][i]; 67 } 68 if(x==y) return x; 69 else return ast[x][0]; 70 } 71 int main(){ 72 scanf("%d%d",&n,&m); 73 cnt=n; 74 int l,r; 75 for(int i=1;i<=m;++i){ 76 scanf("%d%d",&l,&r); 77 ist(l,r); 78 } 79 for(int i=1;i<=n;++i)if(!dfn[i]){ 80 tj(i); 81 --hd; //dfs完了还有一个根,要退栈 82 } 83 gte(); 84 for(int i=1;i<=n;++i)if(f[i]==0){ 85 ft++; 86 dfs(i,0); 87 } 88 scanf("%d",&o); 89 while(o --> 0){ 90 scanf("%d%d",&l,&r); 91 int u=lca(l,r); 92 printf("%d ",s[l]+s[r]-s[u]-s[ast[u][0]]); 93 } 94 return 0; 95 }
平面最近点对:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const double oo=1e16; 7 struct nds{double x,y;}a[210000]; 8 int n; 9 nds b[210000]; 10 nds q[210000]; int hd=0,tl=1; 11 inline double sqr(double x){ return x*x;} 12 inline double dst(nds x,nds y){ 13 return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y)); 14 } 15 double dvs(int l,int r){ 16 if(l==r) return oo; 17 if(l+1==r){ 18 if(a[l].y>a[r].y) swap(a[l],a[r]); //记得两个点也要排序 19 return dst(a[l],a[r]); 20 } 21 int md=(l+r)>>1; 22 double mdx=a[md].x; //注意记录中点坐标,否则排完序就错了 23 double d=min(dvs(l,md),dvs(md+1,r)); 24 int hd1=l,hd2=md+1; 25 for(int i=l;i<=r;++i){ 26 if(hd1>md) b[i]=a[hd2++]; 27 else if(hd2>r) b[i]=a[hd1++]; 28 else if(a[hd1].y<a[hd2].y) b[i]=a[hd1++]; 29 else b[i]=a[hd2++]; 30 } 31 for(int i=l;i<=r;++i) a[i]=b[i]; 32 double mn=d; //注意初值是d而不是oo 33 hd=0,tl=1; 34 for(int i=l;i<=r;++i)if(fabs(a[i].x-mdx)<d){ 35 q[++hd]=a[i]; 36 while(fabs(q[tl].y-q[hd].y)>d) tl++; 37 for(int j=tl;j<hd;++j) mn=min(mn,dst(q[j],a[i])); 38 } 39 return mn; 40 } 41 bool cmp(nds x,nds y){ 42 return x.x<y.x; 43 } 44 int main(){ 45 scanf("%d",&n); 46 for(int i=1;i<=n;++i){ 47 scanf("%lf%lf",&a[i].x,&a[i].y); 48 } 49 sort(a+1,a+n+1,cmp); 50 printf("%.4lf ",dvs(1,n)); 51 return 0; 52 }
KMBFS(严格n^3):
1 ll s[410]; 2 ll e[410][410]; 3 //e[i][j]是左边第i个和右边第j个匹配的贡献 4 int prv[410],nxt[410]; 5 //算法跑完后nxt就是左边匹配的右边 6 //如果nxt[i]为0就表示没匹配 7 ll slc[410]; 8 ll dbx[410],dby[410]; 9 bool vst[410]; 10 void bfs(int x){ 11 int px=0,py=0,yy=0; 12 ll d=oo; 13 for(int i=1;i<=n;++i){ 14 prv[i]=0; 15 slc[i]=oo; 16 } 17 nxt[py]=x; 18 do{ 19 px=nxt[py]; 20 d=oo; 21 vst[py]=1; 22 for(int i=1;i<=n;++i)if(vst[i]==0){ 23 if(slc[i]>dbx[px]+dby[i]-e[px][i]){ 24 slc[i]=dbx[px]+dby[i]-e[px][i]; 25 prv[i]=py; 26 } 27 if(slc[i]<d){ 28 d=slc[i]; 29 yy=i; 30 } 31 } 32 for(int i=0;i<=n;++i){ 33 if(vst[i]){ 34 dbx[nxt[i]]-=d; 35 dby[i]+=d; 36 } 37 else slc[i]-=d; 38 } 39 py=yy; 40 }while(nxt[py]!=0); 41 while(py){ 42 nxt[py]=nxt[prv[py]]; 43 py=prv[py]; 44 } 45 } 46 void km(){ 47 for(int i=1;i<=n;++i){ 48 dbx[i]=0; 49 dby[i]=0; 50 nxt[i]=0; 51 } 52 for(int i=1;i<=n;++i){ 53 for(int j=1;j<=n;++j) vst[j]=0; 54 bfs(i); 55 } 56 } 57 int main(){ 58 e[i][j]=s[bsc(b[i]+c[j])]; 59 km(); 60 ll bwl=0; 61 for(int i=1;i<=n;++i)if(nxt[i]!=0) 62 bwl+=e[nxt[i]][i]; 63 printf("%lld ",bwl); 64 65 }
二次剩余(Python):
1 from random import randint 2 3 4 def mul_i(a, b, t, p): 5 return [(a[0] * b[0] + a[1] * b[1] * t) % p, (a[0] * b[1] + b[0] * a[1]) % p] 6 7 8 def pow_i(a, b, c, t, p): 9 ans = [1, 0] 10 z = [a, b] 11 while c > 0: 12 if c % 2 == 1: 13 ans = mul_i(ans, z, t, p) 14 z = mul_i(z, z, t, p) 15 c = c // 2 16 17 return ans 18 19 20 def legendre(a, p): 21 return pow(a, (p - 1) // 2, p) 22 23 24 def residue(n, p): 25 t = randint(0, p - 1) 26 while legendre(t ** 2 - n, p) != p - 1: 27 t = randint(0, p - 1) 28 29 a = pow_i(t, 1, (p + 1) // 2, t ** 2 - n, p) 30 return a[0] 31 32 33 if __name__ == '__main__': 34 T = int(input()) 35 for t in range(T): 36 n, p = [int(i) for i in input().split(' ')] 37 if legendre(n, p) == p - 1: 38 print('No solution!') 39 elif legendre(n, p) == 0: 40 print(0) 41 else: 42 a = residue(n, p) 43 b = p - a 44 if a > b: 45 a, b = b, a 46 if a == b: 47 print(a) 48 else: 49 print(a, b)
>w<