模板库(持续更新……)
蒟蒻的模板库
突然发现模板什么的需要存一下了= =因为蒟蒻并没有全部记住……
一些算法/数据结构的模板就放自己其他博文的链接了,另一些会在这里直接写下来。
以前的我会慢慢整理……今天先写一个→_→(明显还是在偷懒啊喂!能不能靠谱一点啊?)
数学相关:
1 void add(int k,int v){ 2 // printf("add %d %d\n",k,v); 3 F(j,1,tot){ 4 int x=k; 5 while(x){ 6 b[j]+=x/prime[j]*v; 7 x/=prime[j]; 8 } 9 } 10 }
递推求逆元:
令$a=\lfloor \frac{p}{i}\rfloor$,$b=p\ mod\ i$
则有 $a*i=-b \pmod p$
所以$i^{-1}=-a*b^{-1}$
1 inv[0]=inv[1]=1; 2 F(i,2,n) inv[i]=p-(p/i)*inv[p%i]%p;
原根&将数分拆为 $p_i^{a_i}$ :【BZOJ】【2219】数论之神
1 void Split(int x){ 2 num=0; 3 for(int i=2;i*i<=x;i++) 4 if (x%i==0){ 5 a[++num].p=i; 6 a[num].c=0; a[num].pc=1; 7 while(x%i==0) 8 x/=i,a[num].c++,a[num].pc*=i; 9 if (x==1) break; 10 } 11 if (x!=1) 12 a[++num].p=x,a[num].pc=x,a[num].c=1; 13 }
1 LL Get_yuangen(LL p,LL phi){ 2 int c=0; 3 for(int i=2;i*i<=phi;i++) 4 if (phi%i==0) 5 f[++c]=i,f[++c]=phi/i; 6 for(int g=2;;g++){ 7 int j; 8 for(j=1;j<=c;j++) if (Pow(g,f[j],p)==1) break; 9 if (j==c+1) return g; 10 } 11 return 0; 12 }
高精度:
【BZOJ】【1089】【SCOI2003】严格n元树 代码节选:
1 struct bint{ 2 int l,v[1010]; 3 bint(){l=0;memset(v,0,sizeof v);} 4 int& operator [] (int x){return v[x];} 5 }f[20]; 6 const int Limit=10000; 7 void print(bint a){ 8 printf("%d",a[a.l]); 9 D(i,a.l-1,1) printf("%04d",a[i]); 10 puts(""); 11 } 12 bint operator * (bint a,bint b){ 13 bint c; 14 F(i,1,a.l+b.l) c[i]=0; 15 F(i,1,a.l) F(j,1,b.l) 16 c[i+j-1]+=a[i]*b[j]; 17 c.l=a.l+b.l; 18 F(i,1,c.l) 19 if (c[i]>=Limit){ 20 if (i==c.l){ 21 c.l++; 22 c[i+1]=c[i]/Limit; 23 }else c[i+1]+=c[i]/Limit; 24 c[i]%=Limit; 25 } 26 while(c.l>1 && !c[c.l]) c.l--; 27 return c; 28 } 29 bint operator + (bint a,int p){ 30 a[1]+=p; 31 int now=1; 32 while(a[now]>=Limit){ 33 a[now+1]+=a[now]/Limit; 34 a[now]%=Limit; 35 now++; 36 a.l=max(a.l,now); 37 } 38 return a; 39 } 40 bint operator - (bint a,bint b){ 41 F(i,1,a.l){ 42 a[i]-=b[i]; 43 if (a[i]<0){ 44 a[i]+=Limit; 45 a[i+1]--; 46 } 47 } 48 while(a.l>1 && !a[a.l]) a.l--; 49 return a; 50 } 51 bint operator ^ (bint a,int b){ 52 bint r; r[r.l=1]=1; 53 for(;b;b>>=1,a=a*a) 54 if (b&1) r=r*a; 55 return r; 56 }
【ContestHunter】【弱省胡策】【Round7】高精除单精:
1 void del(bint& a,const int &b){ 2 LL tmp=0,last=0; 3 D(i,a.l,1){ 4 tmp=(a[i]+last*Limit)%b; 5 a[i]=(a[i]+last*Limit)/b; 6 last=tmp; 7 } 8 while(a[a.l]==0 && a.l) a.l--; 9 }
KD-Tree:
建树:
1 void Push_up(int o){ 2 F(i,0,1){ 3 t[o].mn[i]=min(t[o][i],min(t[L].mn[i],t[R].mn[i])); 4 t[o].mx[i]=max(t[o][i],max(t[L].mx[i],t[R].mx[i])); 5 } 6 t[o].sum=t[L].sum+t[R].sum+t[o].v; 7 } 8 9 inline int build(int l,int r,int dir){ 10 D=dir; 11 nth_element(t+l,t+mid,t+r+1); 12 int o=mid; 13 L=l<mid ? build(l,mid-1,dir^1) : 0; 14 R=mid<r ? build(mid+1,r,dir^1) : 0; 15 Push_up(o); 16 return o; 17 }
找第K远点:
1 inline LL dis(Poi a,Poi b){return (LL)sqr(a[0]-b[0])+(LL)sqr(a[1]-b[1]);} 2 inline LL getdis(int o){ 3 if (!o) return -2; 4 LL ans=0; 5 F(i,0,1) 6 ans+=max((LL)sqr(t[o].mx[i]-now[i]),(LL)sqr(t[o].mn[i]-now[i])); 7 return ans; 8 } 9 priority_queue<node>Q; 10 11 void query(int o){ 12 if (!o) return; 13 LL dl=getdis(L),dr=getdis(R),d0=dis(t[o],now); 14 if (d0>Q.top().dis || (d0==Q.top().dis && t[o].num<Q.top().num)){ 15 Q.pop(); Q.push(node(d0,t[o].num)); 16 } 17 if (dl>dr){ 18 if (dl>=Q.top().dis) query(L); 19 if (dr>=Q.top().dis) query(R); 20 }else{ 21 if (dr>=Q.top().dis) query(R); 22 if (dl>=Q.top().dis) query(L); 23 } 24 }
3.【BZOJ】【1941】【SDOI2010】Hide and Seek
找最近/远点:
1 int dis(int a){return abs(t[a][0]-t[tmp][0])+abs(t[a][1]-t[tmp][1]);} 2 int calc_mn(int o){ 3 if (!o) return INF; 4 int ans=0; 5 F(i,0,1) ans+=max(0,t[o].mn[i]-t[tmp][i]); 6 F(i,0,1) ans+=max(0,t[tmp][i]-t[o].mx[i]); 7 return ans; 8 } 9 10 void query_mn(int o){ 11 if (!o) return; 12 int dl=calc_mn(L),dr=calc_mn(R),d0=dis(o); 13 if (d0) ask_mn=min(ask_mn,d0); 14 if (dl<dr){ 15 if (dl<ask_mn) query_mn(L); 16 if (dr<ask_mn) query_mn(R); 17 }else{ 18 if (dr<ask_mn) query_mn(R); 19 if (dl<ask_mn) query_mn(L); 20 } 21 } 22 23 int calc_mx(int o){ 24 if (!o) return -INF; 25 int ans=0; 26 F(i,0,1) ans+=max(abs(t[o].mn[i]-t[tmp][i]),abs(t[o].mx[i]-t[tmp][i])); 27 return ans; 28 } 29 void query_mx(int o){ 30 if (!o) return; 31 int dl=calc_mx(L),dr=calc_mx(R),d0=dis(o); 32 ask_mx=max(ask_mx,d0); 33 if (dl>dr){ 34 if (dl>ask_mx) query_mx(L); 35 if (dr>ask_mx) query_mx(R); 36 }else{ 37 if (dr>ask_mx) query_mx(R); 38 if (dl>ask_mx) query_mx(L); 39 } 40 } 41
Insert:
1 inline void Insert(int &o,int dir){ 2 if (!o){ 3 o=++tot; t[o]=now; 4 F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i]; 5 t[o].D=dir; 6 t[o].size=1; 7 t[o].sum=t[o].v; 8 return; 9 } 10 if (now[dir]<t[o][dir]){ 11 Insert(L,dir^1); 12 Push_up(o); 13 if ((double)t[L].size>(double)t[o].size*0.7) rebuild(o); 14 } 15 else{ 16 Insert(R,dir^1); 17 Push_up(o); 18 if ((double)t[R].size>(double)t[o].size*0.7) rebuild(o); 19 } 20 }
rebuild的姿势:
1 inline int build(int l,int r,int dir){ 2 D=dir; 3 nth_element(p+l,p+mid,p+r+1,cmp); 4 int o=p[mid]; 5 t[o].D=dir; 6 F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i]; 7 t[o].sum=t[o].v; 8 L=l<mid ? build(l,mid-1,dir^1) : 0; 9 R=mid<r ? build(mid+1,r,dir^1) : 0; 10 Push_up(o); 11 return o; 12 } 13 inline void dfs(int o){ 14 if (!o) return; 15 dfs(L); 16 p[++cnt]=o; 17 dfs(R); 18 } 19 inline void rebuild(int &o){ 20 cnt=0; 21 dfs(o); 22 o=build(1,cnt,t[o].D); 23 }
区域求和:
1 int query(int o,int x1,int y1,int x2,int y2){ 2 if (!o) return 0; 3 if (t[o].mn[0]>=x1 && t[o].mn[1]>=y1 && t[o].mx[0]<=x2 && t[o].mx[1]<=y2) 4 return t[o].sum; 5 else{ 6 int ans=0; 7 if (t[o][0]>=x1 && t[o][0]<=x2 && t[o][1]>=y1 && t[o][1]<=y2) ans+=t[o].v; 8 if (t[L].mn[0]>x2 || t[L].mx[0]<x1 || t[L].mn[1]>y2 || t[L].mx[1]<y1) ; 9 else ans+=query(L,x1,y1,x2,y2); 10 if (t[R].mn[0]>x2 || t[R].mx[0]<x1 || t[R].mn[1]>y2 || t[R].mx[1]<y1) ; 11 else ans+=query(R,x1,y1,x2,y2); 12 return ans; 13 } 14 }
可持久化Trie:
(这个板子只是搞异或,不过需要用可持久化Trie的时候……基本都是在搞Xor?)
1 int n,m,q,tot,rt[N],id[M],t[M][2],a[N],b[150][N]; 2 3 inline void Ins(int pre,int x,int k){ 4 int now=rt[k]=++tot; id[tot]=k; 5 D(i,30,0){ 6 int j=(x>>i)&1; 7 t[now][j^1]=t[pre][j^1]; 8 t[now][j]=++tot; id[tot]=k; 9 now=tot; 10 pre=t[pre][j]; 11 } 12 } 13 inline int ask(int l,int r,int x){ 14 int ans=0,now=rt[r]; 15 D(i,30,0){ 16 int j=((x>>i)&1)^1; 17 if (id[t[now][j]]>=l) ans|=1<<i; else j^=1; 18 now=t[now][j]; 19 } 20 return ans; 21 }
判n个区间的交是否为空:
进入区间+1,离开区间-1,每个区间的左右端点都视为一个事件,排序一下,看是否某一时刻前缀和为n即可。
点分治:
【BZOJ】【3697】采药人的路径 & 【3127】【USACO2013 Open】Yin and Yang
1 int n,rt,s[N],h[N],size,dep[N]; 2 bool vis[N]; 3 //LL ans,g[N*2][2],f[N*2][2]; 4 //int t[N<<1],dis[N],mxdeep; 5 6 /* 7 * size=n; h[rt=0]=n+1; 8 getroot(1,0); 9 getans(rt); 10 printf("%lld\n",ans) 11 */ 12 13 inline void getroot(int x,int fa){ 14 s[x]=1; h[x]=0; 15 for(int i=head[x];i;i=nxt[i]) 16 if (to[i]!=fa && !vis[to[i]]){ 17 getroot(to[i],x); 18 s[x]+=s[to[i]]; 19 h[x]=max(h[x],s[to[i]]); 20 } 21 h[x]=max(h[x],size-s[x]); 22 if (h[x]<h[rt]) rt=x; 23 } 24 25 inline void dfs(int x,int fa){ 26 mxdeep=max(mxdeep,dep[x]); 27 if (t[dis[x]]) g[dis[x]][1]++; 28 else g[dis[x]][0]++; 29 t[dis[x]]++; 30 for(int i=head[x];i;i=nxt[i]) 31 if (!vis[to[i]] && to[i]!=fa){ 32 dep[to[i]]=dep[x]+1; 33 dis[to[i]]=dis[x]+v[i]; 34 dfs(to[i],x); 35 } 36 t[dis[x]]--; 37 }//用来得到所需的子树的信息 38 39 inline void getans(int x){ 40 int mx=0; 41 vis[x]=1; f[n][0]=1; 42 for(int i=head[x];i;i=nxt[i]) 43 if (!vis[to[i]]){ 44 //xxxxx 45 dfs(to[i],x); 46 //xxxxx 47 } 48 F(i,n-mx,n+mx) f[i][0]=f[i][1]=0; 49 //清空统计数组 50 51 //统计答案↑ 52 for(int i=head[x];i;i=nxt[i]) 53 if (!vis[to[i]]){ 54 rt=0; size=s[to[i]]; 55 getroot(to[i],x); 56 getans(rt); 57 } 58 //继续分治↑ 59 }
平衡树维护凸包:
http://blog.csdn.net/auto_ac/article/details/10664641
【ContestHunter】【弱省胡策】【Round8】(加了维护斜率/凸包上二分)
1 typedef map<double,double> mii; 2 typedef map<double,double>::iterator iter; 3 #define X first 4 #define Y second 5 double cross(iter o,iter a,iter b){ 6 return (a->X - o->X) * (b->Y - o->Y) - 7 (a->Y - o->Y) * (b->X - o->X); 8 } 9 mii up,slop; 10 11 inline double slope(iter a,iter b){ 12 return (b->Y - a->Y)/(b->X - a->X); 13 } 14 bool inside(mii &p,double x,double y){ 15 if (!p.size()) return 0; 16 if (x<p.begin()->X || x>p.rbegin()->X) return 0; 17 if (p.count(x)) return y<=p[x]; 18 p[x]=y; 19 iter cur = p.lower_bound(x),i,j; 20 i=j=cur; i--; j++; 21 bool ret=cross(i,cur,j)>=0; 22 p.erase(cur); 23 return ret; 24 } 25 void add(mii &p,double x,double y){ 26 if (inside(p,x,y)) return; 27 if (p.count(x)){ 28 iter cur=p.lower_bound(x),i=cur,j=cur; 29 i--;j++; 30 if (cur!=p.begin()) slop.erase(slope(i,cur)); 31 if (j!=p.end()) slop.erase(slope(cur,j)); 32 } 33 p[x]=y; 34 iter cur=p.lower_bound(x),i=cur,j=cur; 35 i--; j++; 36 if (cur!=p.begin() && j!=p.end()) slop.erase(slope(i,j)); 37 if (cur!=p.begin()) slop[slope(i,cur)]=cur->X; 38 if (j!=p.end()) slop[slope(cur,j)]=j->X; 39 for(i=cur,i--,j=i,j--;i!=p.begin() && cur!=p.begin();i=j--) 40 if (cross(j,i,cur)>=0){ 41 slop.erase(slope(j,i)); 42 slop.erase(slope(i,cur)); 43 slop[slope(j,cur)]=cur->X; 44 p.erase(i); 45 } 46 else break; 47 for(i=cur,i++,j=i,j++;i!=p.end() && j!=p.end();i=j++) 48 if (cross(cur,i,j)>=0){ 49 slop.erase(slope(cur,i)); 50 slop.erase(slope(i,j)); 51 slop[slope(cur,j)]=j->X; 52 p.erase(i); 53 } 54 else break; 55 } 56 double query(double k){ 57 double x,y; 58 iter it=slop.lower_bound(k); 59 if (it==slop.end()) x=up.begin()->X,y=up.begin()->Y; 60 else x=it->Y,y=up[x]; 61 // printf("query k=%f tmpk=%f x=%f y=%f\n",k,it->X,x,y); 62 return y-k*x; 63 }