板子-GOD BLESS ALL OF YOU
字符串:
KMP
#include<cstdio> #include<cstring> const int N=1000004; char s1[N],s2[N/100]; int next[N/100]; int l1,l2; void get_next() { next[0]=-1; for(int i=2,j=0;i<=l2;++i) { for(;s2[i]!=s2[j+1]&&j>0;j=next[j]); if(s2[i]==s2[j+1])next[i]=++j; } } void kmp() { for(int i=1,j=0;i<=l1;i++) { for(;s1[i]!=s2[j+1]&&j>0;j=next[j]); if(s1[i]==s2[j+1])++j; if(j==l2) printf("%d\n",i-l2+1),j=next[l2]; } } int main() { scanf("%s%s",s1+1,s2+1); l1=strlen(s1+1); l2=strlen(s2+1); get_next(); kmp(); for(int i=1;i<=l2;i++) { printf("%d ",next[i]); } return 0; }
AC自动机last指针版
#include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxn = 100001; int n; char s[maxn][101]; char ss[maxn*10]; int ans=0; struct Aho_Corasick_automato { int sz; int ch[maxn][26]; int cnt[maxn]; int val[maxn]; int last[maxn]; int fail[maxn]; int num; void init() { memset(ch[0],0,sizeof(ch[0])); memset(cnt,0,sizeof(cnt)); sz=1; } void insert(char *s,int num) { int len=strlen(s); int u=0; for(int i=0; i<len; ++i) { int v=(s[i]-'a'); if(!ch[u][v]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][v]=sz++; } u=ch[u][v]; } val[u]=num; } void get_fail() { fail[0]=0; queue<int>que; for(int i=0; i<26; i++) { int u=ch[0][i]; if(u) { fail[u]=0; que.push(u); } } while(!que.empty()) { int u=que.front(); que.pop(); for(int i=0; i<26; i++) { int v=ch[u][i]; if(!v) { ch[u][i]=ch[fail[u]][i]; continue; } que.push(v); int k=fail[u]; fail[v]=ch[k][i]; last[v]=val[fail[v]] ? fail[v] : last[fail[v]]; } } } void work(int x) { if(x) { cnt[val[x]]++; work(last[x]); } } void find(char *s) { int len=strlen(s); int u=0; for(int i=0; i<len; i++) { int v=(s[i]-'a'); if(!ch[u][v])u=fail[u]; while(u&&!ch[u][v]) u=fail[u]; u=ch[u][v]; if(val[u]) work(u); else if(last[u]) work(last[u]); } } } ac; int main() { while(scanf("%d",&n)==1&&n!=0) { ac.init(); for(int i=1; i<=n; i++) { scanf("%s",s[i]); ac.insert(s[i],i); } ac.get_fail(); scanf("%s",ss); ac.find(ss); int ans=0,r; for(int i=1;i<=n;i++) if(ac.cnt[i]>ans)ans=ac.cnt[i],r=i;; printf("%d\n",ans); for(int r=1;r<=n;r++) if(ac.cnt[r]==ans) printf("%s\n",s[r]); } return 0; }
马拉车
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 33000000 int n,p[N],ans; char s[N],str[N]; void manachar() { int mx=0,id; for(int i=n; str[i]!=0; i++)str[i]=0; for(int i=1; i<n; i++) { if(mx>i) p[i]=min(p[2*id-i],p[id]+id-i); else p[i]=1; for(;str[i+p[i]]==str[i-p[i]];++p[i]); if(p[i]+i>mx) mx=p[i]+i, id=i; } } void csh() { str[0]='#'; str[1]='#'; for(int i=0;i<n;i++) str[(i<<1)+2]=s[i],str[(i<<1)+3]='#'; n=(n<<1)+2; str[n]=0; } int main() { scanf("%s",s); n=strlen(s); csh(); manachar(); ans=0; for(int i=0;i<n;i++) ans=max(ans,p[i]); printf("%d\n",ans-1); return 0; }
字符串hash
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef unsigned long long ull; ull base = 131; char s[100000]; ull a[100000]; ull hashs(char *s) { int len=strlen(s); ull ans=0; for(int i=0;i<len;i++) ans=ans*base+(ull)s[i]; return ans&0x7fffffff; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s",s); a[i]=hashs(s); } sort(a+1,a+n+1); int ans=0; for(int i=2;i<=n;i++) if(a[i]!=a[i-1]) ans++; printf("%d\n",++ans); return 0; }
后缀数组
#include<cstdio> #include<cstring> #include<algorithm> using std::swap; const int maxn=2000010; char c[maxn]; int s[maxn],sa[maxn];//后缀排名的位置 int rank[maxn];//后缀排名 int height[maxn];//常规操作 int saf[maxn];//用saf[]作为第2关键字后缀的第一关键字 int cs[maxn];//基数排序中的排名计数器 int n,m; void rsort() {//第二关键字基数排序 for(int i=0;i<=m;++i)cs[i]=0; for(int i=1;i<=n;++i)cs[rank[saf[i]]]++; for(int i=1;i<=m;++i)cs[i]+=cs[i-1]; for(int i=n;i>=1;--i)sa[cs[rank[saf[i]]]--]=saf[i];//利用第二关键字排名更新sa } int cmp(int *f,int x,int y,int w) { return f[x]==f[y]&&f[x+w]==f[y+w];//cmp } void get_sa() { for(int i=1;i<=n;++i)rank[i]=s[i],saf[i]=i;//此时saf[i]指向自己作为第一关键字的后缀 m=127;rsort(); for(int p=1,w=1,i;p<n;w<<=1,m=p) {//w为倍增长度,<选取第几位作为第二关键字> for(i=n-w+1,p=0;i<=n;++i)saf[++p]=i; for(i=1;i<=n;++i)if(sa[i]>w)saf[++p]=sa[i]-w;//利用上次的sa[]值更新下一次的saf[],有的字母已经不能再作为后缀的第n位的关键字了0 rsort();swap(rank,saf);rank[sa[1]]=p=1;//p用来记录已经不需要再比较'第三关键字的'的后缀//当p=n是说明排序完成 for(i=2;i<=n;++i)rank[sa[i]]=cmp(saf,sa[i],sa[i-1],w)?p:++p;//比较第一关键词与自己排名相临的,若第二关键字相同则需继续比较 } //int j,k=0; //for(int i=1;i<=n;height[rank[i++]]=k) // for(k=k?k-1:k,j=sa[rank[i]-1];s[i+k]==s[j+k];++k); } int main() { scanf("%s",c+1); n=strlen(c+1); for(int i=1;i<=n;++i)s[i]=c[i]; s[0]=s[n+1]=-1; get_sa(); for(int i=1;i<=n;++i) { printf("%d ",sa[i]); } return 0; }
数据结构
手写heap
void put(int r) { while(r>1&&a[r]<a[r/2]) { h=a[r]; a[r]=a[r/2]; a[r/2]=h; r/=2; } } int flag=1; int get()//弹出最小值 { if(flag==1) { sum=a[1]; flag=0; } else sum+=a[1]; a[1]=a[len]; len--; r=1; while((r*2<=len&&a[r]>a[r*2])||(r*2+1<=len&&a[r]>a[r*2+1])) { j=r*2; if(j+1<=len&&a[j]>a[j+1])j++; h=a[r]; a[r]=a[j]; a[j]=h; r=j; } }
树状数组
1单点修改+区间查询
//树状数组:区间查询,单点修改 #include<cstdio> int sum[500100]; int n,m; int lowbit(int x) { return x&(-x); } void update(int x,int v) { while (x<=n) { sum[x] += v; x += lowbit(x); } } int query(int x) { int ans = 0; while (x) { ans += sum[x]; x -= lowbit(x); } return ans; } int main() { scanf("%d%d",&n,&m); for (int a,i=1; i<=n; ++i) { scanf("%d",&a); update(i,a); } for (int i=1; i<=m; ++i) { int x,y,z; scanf("%d%d%d",&z,&x,&y); if (z==1) update(x,y); //单点修改 else printf("%d\n",query(y)-query(x-1)); } return 0; }
2区间修改+单点查询
//树状数组:区间修改,单点查询,差分 #include<cstdio> int sum[500100]; int n,m,last = 0; int lowbit(int x) { return x&(-x); } void update(int x,int v) { while (x<=n) { sum[x] += v; x += lowbit(x); } } int query(int x) { int ans = 0; while (x) { ans += sum[x]; x -= lowbit(x); } return ans; } int main() { scanf("%d%d",&n,&m); for (int a,i=1; i<=n; ++i) { scanf("%d",&a); update(i,a-last); last = a; } for (int x,y,z,a,i=1; i<=m; ++i) { scanf("%d",&a); if (a==1) //区间修改 { scanf("%d%d%d",&x,&y,&z); update(x,z); update(y+1,-z); } else //单点查询 { scanf("%d",&x); printf("%d\n",query(x)); } } return 0; }
可持久化线段树(状态区间和)
#include<cstdio> #include<iostream> using namespace std; #define N 100001 int n,m,cnt,ans; int root[N*20]; int ls[N*20],sum[N*20],rs[N*20]; int ope[N]; void change(int l,int r,int &rt,int pre,int pos,int w) { if(!rt)rt=++cnt; sum[rt]=sum[pre]; if(l==r){sum[rt]=w;return;} int mid=(l+r)>>1; if(pos<=mid)rs[rt]=rs[pre],change(l,mid,ls[rt],ls[pre],pos,w); else ls[rt]=ls[pre],change(mid+1,r,rs[rt],rs[pre],pos,w); sum[rt]=sum[ls[rt]]+sum[rs[rt]]; } void query(int l,int r,int rt,int opl,int opr) { if(opl<=l&&opr>=r){ ans+=sum[rt];return ; } int mid=(l+r)>>1; if(opl<=mid)query(l,mid,ls[rt],opl,opr); if(opr>mid)query(mid+1,r,rs[rt],opl,opr); } int main() { scanf("%d%d",&n,&m); int x,y,z; for(int i=1;i<=n;i++) scanf("%d",&x),change(1,n,root[0],root[0],i,x); char s[3]; int now=0; for(int i=1;i<=m;i++) { ope[i]=now; scanf("%s",s); if(s[0]=='M') { now++; ope[i]=now; scanf("%d%d",&x,&y); change(1,n,root[now],root[now-1],x,y); } else { scanf("%d%d%d",&x,&y,&z); ans=0; query(1,n,root[ope[z]],x,y); printf("%d\n",ans); } } return 0; }
主席树k大值
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N = 100001; int ls[N*20],rs[N*20],sum[N*20]; int n,m,a[N],hash[N],cnt,root[N]; int x,y,k; void lsh() { sort(hash+1,hash+n+1); cnt=unique(hash+1,hash+n+1)-(hash+1); for(int i=1;i<=n;i++)a[i]=lower_bound(hash+1,hash+cnt+1,a[i])-hash; } int tot=0; void build(int l,int r,int &rt,int pre,int w) { rt=++tot; sum[rt]=sum[pre]+1; if(l==r)return; int mid=(l+r)>>1; if(w<=mid)rs[rt]==rs[pre],build(l,mid,ls[rt],ls[pre],w); else ls[rt]=ls[pre],build(mid+1,r,rs[rt],rs[pre],w); } int query(int l,int r,int x,int y,int k) { if(l==r)return l; int mid=l+r>>1,tmp=sum[ls[y]]-sum[ls[x]]; if(tmp>=k)return query(l,mid,ls[x],ls[y],k); else return query(mid+1,r,rs[x],rs[y],k-tmp); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",a+i),hash[i]=a[i]; lsh(); // printf("%d\n",cnt);for(int i=1;i<=cnt;i++) printf("%d ",hash[i]); for(int i=1;i<=n;i++) build(1,cnt,root[i],root[i-1],a[i]); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&k); printf("%d\n",hash[query(1,cnt,root[x-1],root[y],k)]); } return 0; }
Splay tree 区间翻转区间标记
#include<cstdio> #include<iostream> using namespace std; #define N 100005 int n,m; struct node{ int siz,fa,ch[2];//0zuo,1you; bool rev; }tr[N]; int root; void push_down(int rt) { if(tr[rt].rev) { swap(tr[rt].ch[1],tr[rt].ch[0]); tr[rt].rev=0; tr[tr[rt].ch[0]].rev^=1;tr[tr[rt].ch[1]].rev^=1; } } void pushup(int rt) { tr[rt].siz=tr[tr[rt].ch[0]].siz+tr[tr[rt].ch[1]].siz+1; return; } int find(int rt,int x) { if(rt==0)return 0; push_down(rt); if(x<=tr[tr[rt].ch[0]].siz)return find(tr[rt].ch[0],x); if(x==tr[tr[rt].ch[0]].siz+1)return rt; return find(tr[rt].ch[1],x-tr[tr[rt].ch[0]].siz-1); } void rotate(int &rt,int x) { int y=tr[x].fa,q=tr[y].fa; bool dy=tr[y].ch[1]==x,dz=tr[q].ch[1]==y; push_down(y); if(rt==y)rt=x,tr[x].fa=q; else tr[q].ch[dz]=x,tr[x].fa=q; tr[y].ch[dy]=tr[x].ch[dy^1],tr[tr[x].ch[dy^1]].fa=y; tr[x].ch[dy^1]=y,tr[y].fa=x; pushup(y); return ; } void splay(int &rt,int x) { push_down(x); while(rt!=x) { int y=tr[x].fa;int q=tr[y].fa; if(y!=rt) { if(tr[y].ch[1]==x^tr[q].ch[1]==y)rotate(rt,x); else rotate(rt,y); } rotate(rt,x); } pushup(x); return; } void print(int rt) { if(rt==0)return; push_down(rt); print(tr[rt].ch[0]); if(rt>1&&rt<n+2)printf("%d ",rt-1); print(tr[rt].ch[1]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n+2;i++) { tr[i].siz=n+3-i;tr[i].fa=i-1;tr[i].ch[1]=i+1; } tr[n+2].ch[1]=0,root=1; while(m--) { int l,r; scanf("%d%d",&l,&r); splay(root,find(root,l)); splay(tr[root].ch[1],find(root,r+2)); tr[tr[tr[root].ch[1]].ch[0]].rev^=1; } print(root); return 0; }
Splay基本操作插入,删除,k大,值rank,前驱,后继
#include<cstdio> #include<iostream> using namespace std; #define N 100005 int n,m; struct node{ int siz,fa,ch[2];//0zuo,1you; bool rev; }tr[N]; int root; void push_down(int rt) { if(tr[rt].rev) { swap(tr[rt].ch[1],tr[rt].ch[0]); tr[rt].rev=0; tr[tr[rt].ch[0]].rev^=1;tr[tr[rt].ch[1]].rev^=1; } } void pushup(int rt) { tr[rt].siz=tr[tr[rt].ch[0]].siz+tr[tr[rt].ch[1]].siz+1; return; } int find(int rt,int x) { if(rt==0)return 0; push_down(rt); if(x<=tr[tr[rt].ch[0]].siz)return find(tr[rt].ch[0],x); if(x==tr[tr[rt].ch[0]].siz+1)return rt; return find(tr[rt].ch[1],x-tr[tr[rt].ch[0]].siz-1); } void rotate(int &rt,int x) { int y=tr[x].fa,q=tr[y].fa; bool dy=tr[y].ch[1]==x,dz=tr[q].ch[1]==y; push_down(y); if(rt==y)rt=x,tr[x].fa=q; else tr[q].ch[dz]=x,tr[x].fa=q; tr[y].ch[dy]=tr[x].ch[dy^1],tr[tr[x].ch[dy^1]].fa=y; tr[x].ch[dy^1]=y,tr[y].fa=x; pushup(y); return ; } void splay(int &rt,int x) { push_down(x); while(rt!=x) { int y=tr[x].fa;int q=tr[y].fa; if(y!=rt) { if(tr[y].ch[1]==x^tr[q].ch[1]==y)rotate(rt,x); else rotate(rt,y); } rotate(rt,x); } pushup(x); return; } void print(int rt) { if(rt==0)return; push_down(rt); print(tr[rt].ch[0]); if(rt>1&&rt<n+2)printf("%d ",rt-1); print(tr[rt].ch[1]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n+2;i++) { tr[i].siz=n+3-i;tr[i].fa=i-1;tr[i].ch[1]=i+1; } tr[n+2].ch[1]=0,root=1; while(m--) { int l,r; scanf("%d%d",&l,&r); splay(root,find(root,l)); splay(tr[root].ch[1],find(root,r+2)); tr[tr[tr[root].ch[1]].ch[0]].rev^=1; } print(root); return 0; }
treap
#include<cstdio> #include<cstdlib> #include<ctime> #define N 500007 int inline read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int tree[N][2],val[N],key[N],siz[N],sz; inline void update(int x) { siz[x]=1+siz[tree[x][0]]+siz[tree[x][1]]; } int make_new(int v) { siz[++sz]=1; val[sz]=v; key[sz]=rand(); return sz; } int merge(int x,int y) { if(!x) return y; else if(!y)return x; if(key[x]<key[y]) { tree[x][1]=merge(tree[x][1],y); update(x); return x; } else { tree[y][0]=merge(x,tree[y][0]); update(y); return y; } } void split(int now,int k,int &x,int &y) {//根据插入数的val值,把树分为小于等于k的,和大于k的 if (!now) x=y=0;//指针为空 else { if (val[now]<=k) x=now,split(tree[now][1],k,tree[now][1],y);//访问右子树 else y=now,split(tree[now][0],k,x,tree[now][0]);//访问左子树 update(now); } } int kth(int now,int k) { while(1) { if (k<=siz[tree[now][0]]) now=tree[now][0]; else if (k==siz[tree[now][0]]+1) return now; else k-=siz[tree[now][0]]+1,now=tree[now][1]; } } int main() { //srand((unsigned)time(NULL)); int T,op,x,y,z,a,b,root=0; scanf("%d",&T); while(T--) { op=read(),a=read(); if (op==1) { split(root,a,x,y); root=merge(merge(x,make_new(a)),y); } else if (op==2) { split(root,a,x,z); split(x,a-1,x,y); y=merge(tree[y][0],tree[y][1]); root=merge(merge(x,y),z); } else if (op==3) { split(root,a-1,x,y); printf("%d\n",siz[x]+1); root=merge(x,y); } else if (op==4) printf("%d\n",val[kth(root,a)]); else if (op==5) { split(root,a-1,x,y); printf("%d\n",val[kth(x,siz[x])]); root=merge(x,y); } else { split(root,a,x,y); printf("%d\n",val[kth(y,1)]); root=merge(x,y); } } return 0; }
树链剖分(树上求和/树上最值)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int MAXN=2*1e6+10; 6 #define ls k<<1 7 #define rs k<<1|1 8 inline int read() { 9 char c=getchar(); 10 int x=0,f=1; 11 while(c<'0'||c>'9') { 12 if(c=='-')f=-1; 13 c=getchar(); 14 } 15 while(c>='0'&&c<='9') 16 x=x*10+c-'0',c=getchar(); 17 return x*f; 18 } 19 struct node { 20 int u,v,nxt; 21 } edge[MAXN]; 22 int head[MAXN]; 23 int num=1; 24 struct Tree { 25 int l,r,w,siz,f; 26 } T[MAXN]; 27 int N,M,root,MOD,cnt=0,a[MAXN],b[MAXN]; 28 inline void AddEdge(int x,int y) { 29 edge[num].u=x; 30 edge[num].v=y; 31 edge[num].nxt=head[x]; 32 head[x]=num++; 33 } 34 int deep[MAXN],fa[MAXN],son[MAXN],tot[MAXN],top[MAXN],idx[MAXN]; 35 int dfs1(int now,int f,int dep) { 36 deep[now]=dep; 37 fa[now]=f; 38 tot[now]=1; 39 int maxson=-1; 40 for(int i=head[now]; i!=-1; i=edge[i].nxt) { 41 if(edge[i].v==f) continue; 42 tot[now]+=dfs1(edge[i].v,now,dep+1); 43 if(tot[edge[i].v]>maxson) maxson=tot[edge[i].v],son[now]=edge[i].v; 44 } 45 return tot[now]; 46 } 47 void update(int k) { 48 T[k].w=(T[ls].w+T[rs].w+MOD)%MOD; 49 } 50 void Build(int k,int ll,int rr) { 51 T[k].l=ll; 52 T[k].r=rr; 53 T[k].siz=rr-ll+1; 54 if(ll==rr) { 55 T[k].w=a[ll]; 56 return ; 57 } 58 int mid=(ll+rr)>>1; 59 Build(ls,ll,mid); 60 Build(rs,mid+1,rr); 61 update(k); 62 } 63 void dfs2(int now,int topf) { 64 idx[now]=++cnt; 65 a[cnt]=b[now]; 66 top[now]=topf; 67 if(!son[now]) return ; 68 dfs2(son[now],topf); 69 for(int i=head[now]; i!=-1; i=edge[i].nxt) 70 if(!idx[edge[i].v]) 71 dfs2(edge[i].v,edge[i].v); 72 } 73 void pushdown(int k) { 74 if(!T[k].f) return ; 75 T[ls].w=(T[ls].w+T[ls].siz*T[k].f)%MOD; 76 T[rs].w=(T[rs].w+T[rs].siz*T[k].f)%MOD; 77 T[ls].f=(T[ls].f+T[k].f)%MOD; 78 T[rs].f=(T[rs].f+T[k].f)%MOD; 79 T[k].f=0; 80 } 81 void IntervalAdd(int k,int ll,int rr,int val) { 82 if(ll<=T[k].l&&T[k].r<=rr) { 83 T[k].w+=T[k].siz*val; 84 T[k].f+=val; 85 return ; 86 } 87 pushdown(k); 88 int mid=(T[k].l+T[k].r)>>1; 89 if(ll<=mid) IntervalAdd(ls,ll,rr,val); 90 if(rr>mid) IntervalAdd(rs,ll,rr,val); 91 update(k); 92 } 93 void TreeAdd(int x,int y,int val) { 94 while(top[x]!=top[y]) { 95 if(deep[top[x]]<deep[top[y]]) swap(x,y); 96 IntervalAdd(1,idx[ top[x] ],idx[x],val); 97 x=fa[ top[x] ]; 98 } 99 if(deep[x]>deep[y]) swap(x,y); 100 IntervalAdd(1,idx[x],idx[y],val); 101 } 102 int IntervalSum(int k,int ll,int rr) { 103 int ans=0; 104 if(ll<=T[k].l&&T[k].r<=rr) 105 return T[k].w; 106 pushdown(k); 107 int mid=(T[k].l+T[k].r)>>1; 108 if(ll<=mid) ans=(ans+IntervalSum(ls,ll,rr))%MOD; 109 if(rr>mid) ans=(ans+IntervalSum(rs,ll,rr))%MOD; 110 return ans; 111 } 112 void TreeSum(int x,int y) { 113 int ans=0; 114 while(top[x]!=top[y]) { 115 if(deep[top[x]]<deep[top[y]]) swap(x,y); 116 ans=(ans+IntervalSum(1,idx[ top[x] ],idx[x]))%MOD; 117 x=fa[ top[x] ]; 118 } 119 if(deep[x]>deep[y]) swap(x,y); 120 ans=(ans+IntervalSum(1,idx[x],idx[y]))%MOD; 121 printf("%d\n",ans); 122 } 123 int main() { 124 memset(head,-1,sizeof(head)); 125 N=read(); M=read(); 126 root=read(); 127 MOD=read(); 128 for(int i=1; i<=N; i++) b[i]=read(); 129 for(int i=1; i<=N-1; i++) { 130 int x=read(),y=read(); 131 AddEdge(x,y); 132 AddEdge(y,x); 133 } 134 dfs1(root,0,1); 135 dfs2(root,root); 136 Build(1,1,N); 137 while(M--) { 138 int opt=read(),x,y,z; 139 if(opt==1) { 140 x=read(); 141 y=read(); 142 z=read(); 143 z=z%MOD; 144 TreeAdd(x,y,z); 145 } else if(opt==2) { 146 x=read(); 147 y=read(); 148 TreeSum(x,y); 149 } else if(opt==3) { 150 x=read(),z=read(); 151 IntervalAdd(1,idx[x],idx[x]+tot[x]-1,z%MOD); 152 } else if(opt==4) { 153 x=read(); 154 printf("%d\n",IntervalSum(1,idx[x],idx[x]+tot[x]-1)); 155 } 156 } 157 return 0; 158 }
link cut tree
1 #include<cstdio> 2 #include<algorithm> 3 const int maxn = 320007; 4 inline int read() { 5 int x=0,f=1;char c=getchar(); 6 while(c<'0'||c>'9') { 7 if(c=='-')f=-1;c=getchar(); 8 } 9 while(c<='9'&&c>='0') { 10 x=x*10+c-'0',c=getchar(); 11 } 12 return x*f; 13 } 14 #define lc ch[x][0] 15 #define rc ch[x][1] 16 bool rev[maxn]; 17 int stack[maxn],top; 18 int ans[maxn],v[maxn]; 19 int fa[maxn],ch[maxn][2]; 20 bool isroot(int x) { 21 return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x; 22 } 23 void update(int x){ 24 ans[x]=ans[lc]^ans[rc]^v[x]; 25 } 26 void pushdown(int x) { 27 if(rev[x]) { 28 rev[x]=0;rev[lc]^=1;rev[rc]^=1; 29 std::swap(lc,rc); 30 } 31 return; 32 } 33 void rotate(int x) { 34 int y=fa[x],z=fa[y],d=(ch[y][1]==x)^1; 35 if(!isroot(y)) ch[z][ch[z][1]==y]=x; 36 fa[x]=z; 37 ch[y][d^1]=ch[x][d],fa[ch[x][d]]=y; 38 ch[x][d]=y;fa[y]=x; 39 return update(y),update(x); 40 } 41 void splay(int x) { 42 stack[++top]=x; 43 for(int i=x;!isroot(i);i=fa[i]) 44 stack[++top]=fa[i]; 45 while(top)pushdown(stack[top--]); 46 while(!isroot(x)) { 47 int y=fa[x],z=fa[y]; 48 if(!isroot(y)) { 49 if(ch[y][1]==x^ch[z][1]==y)rotate(x); 50 else rotate(y); 51 } 52 rotate(x); 53 } 54 return ; 55 } 56 void access(int x) { 57 for(int i=0;x;i=x,x=fa[x]) { 58 splay(x),ch[x][1]=i,update(x); 59 } 60 return ; 61 } 62 void makeroot(int x) { 63 access(x);splay(x);rev[x]^=1; 64 return; 65 } 66 void split(int x,int y) { 67 makeroot(x),access(y);return splay(y); 68 } 69 void cut(int x,int y) { 70 split(x,y); 71 ch[y][0]=fa[ch[y][0]]=0; 72 return; 73 } 74 void link(int x,int y) { 75 makeroot(x),fa[x]=y;return splay(x); 76 } 77 int find(int x) { 78 for(access(x),splay(x);ch[x][0];x=ch[x][0]); 79 return x; 80 } 81 int query(int x,int y) { 82 split(x,y); 83 return ans[y]; 84 } 85 void modify(int x,int w) { 86 access(x),splay(x),v[x]=w; 87 return update(x); 88 } 89 int main() { 90 int n,m; 91 n=read(),m=read(); 92 for(int i=1;i<=n;++i) { 93 v[i]=read();ans[i]=v[i]; 94 } 95 for(int op,x,y,i=1;i<=m;++i) { 96 op=read(),x=read(),y=read(); 97 if(!op) 98 printf("%d\n",query(x,y)); 99 else if(op==1) { 100 if(find(x)!=find(y)) link(x,y); 101 } 102 else if(op==2) { 103 if(find(x)==find(y))cut(x,y); 104 } 105 else modify(x,y); 106 } 107 return 0; 108 }
左偏树
#include<cstdio> #include<algorithm> inline int read() { int x=0;char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); return x; } const int maxn = 100010; struct node { int fa,dis,key,ch[2]; node() { key=fa=dis=0; } }tree[maxn]; inline int ls(int x) {return tree[x].ch[0];} inline int rs(int x) {return tree[x].ch[1];} int n,m; int find(int x) { if(tree[x].fa) return find(tree[x].fa); else return x; } inline void update(int x) { tree[x].dis=tree[tree[x].ch[1]].dis+1; } int merge(int x,int y) { if(!x||!y)return x+y; if(tree[x].key>tree[y].key||(tree[x].key==tree[y].key&&x>y))std::swap(x,y); tree[x].ch[1]=merge(tree[x].ch[1],y); tree[tree[x].ch[1]].fa=x; if(tree[tree[x].ch[1]].dis>tree[tree[x].ch[0]].dis)std::swap(tree[x].ch[0],tree[x].ch[1]); update(x); return x; } void delet(int x) { int now=tree[x].fa;int top=merge(tree[x].ch[1],tree[x].ch[0]); tree[top].fa=now;tree[x].key=-1; while(now) { if(tree[tree[now].ch[0]].dis<tree[tree[now].ch[1]].dis)std::swap(tree[now].ch[0],tree[now].ch[1]); if(tree[now].dis==tree[tree[now].ch[1]].dis+1)return; tree[now].dis=tree[tree[now].ch[1]].dis+1; now=tree[now].fa; } } int main() { n=read(),m=read(); for(int i=1;i<=n;++i) tree[i].key=read(); while(m--) { int op=read(); if(op==1) { int x=read(),y=read(); if(tree[x].key==-1||tree[y].key==-1||x==y)continue; merge(find(x),find(y)); } else { int x=read(); if(tree[x].key==-1)puts("-1"); else x=find(x), printf("%d\n",tree[x].key), delet(x); } } return 0; }
单调队列(两端扩展最大距离(最小值))
#include<cstdio> #include<algorithm> using namespace std; #define LL long long const int maxn= 2000007; #ifdef WIN32 #define lld "I64d" #else #define lld "lld" #endif inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();return x; } int a[maxn],b[maxn]; int l[maxn],r[maxn],tmp[maxn],q[maxn]; int n,m; void work(int c[] ,int d[]) { q[1]=c[1]; tmp[1]=1; int head=1,tail=1; for(int i=2;i<=n;++i) { while(head<=tail&&q[tail]>c[i]) d[tmp[tail--]]=i-1; q[++tail]=c[i]; tmp[tail]=i; } while(head<=tail) d[tmp[head++]]=n; } int main() { LL ans=0; n=read(); for(int i=1;i<=n;++i) a[i]=read(),b[n-i+1]=a[i]; work(a,r); work(b,l); for(int i=1;i<=n;++i) tmp[i]=l[i]; for(int i=1;i<=n;++i) l[n-i+1]=n-tmp[i]+1; for(int i=1;i<=n;++i) ans=max(ans,1ll*a[i]*(r[i]-l[i]+1)); printf("%lld\n",ans); return 0; } 单调队列
并查集安置合并
int cnt = 0 ,fa[maxn],deep[maxn],siz[maxn],v[maxn]; int find(int x) { if(fa[x] != x) { int f = find(fa[x]); deep[x] = deep[fa[x]] + 1; return f; } else return x; } void Union(int x,int y,int C) { int f1 = find(x),f2 = find(y); if(f1 == f2) return ; if(siz[f1] > siz[f2]) fa[f2] = f1,v[f2] = C,siz[f1] += siz[f2]; else fa[f1] = f2,v[f1] = C,siz[f2] += siz[f1]; } int query(int x,int y) { int f1 = find(x),f2 = find(y); if(f1 != f2)return 0; int ret = 0 ; for(;x != y;) { if(deep[x] < deep[y]) swap(x,y); ret = max(ret,v[x]),x = fa[x]; } return ret; }
AC自动机
fail树
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0'||c > '9')c = getchar(); while(c <= '9' &&c >= '0')x = x * 10 + c - '0',c = getchar(); return x * f; } #define LL long long int n; const int maxn = 1000097; char a[maxn]; int sz,ch[maxn][27];LL cnt[maxn]; struct node { int v,next; } edge[maxn << 1]; int num,head[maxn],loc[maxn]; inline void add_edge(int u,int v) { edge[++ num].v = v ;edge[num].next = head[u];head[u] = num; } int insert(char *t) { int len = strlen(t); int now = 0; for(int i = 0;i < len;++ i) { int s = t[i] - 'a'; if(!ch[now][s]) ch[now][s] = ++ sz; now = ch[now][s]; cnt[now] ++; } return now; } int fail[maxn],q[maxn]; void get_fail(int l = 0,int r = 0 ) { for(int i = 0;i <= 25;++ i)if(ch[0][i]) q[++ r] = ch[0][i]; while(l < r) { int u = q[++ l]; for(int i = 0;i <= 25;++ i) { int v = ch[u][i]; if(v) fail[v] = ch[fail[u]][i],q[++ r] = v; else ch[u][i] = ch[fail[u]][i]; } } } void dfs(int x,int fa = 0) { for(int i = head[x];i;i = edge[i].next) { int v = edge[i].v; if(v != fa) {dfs(v,x),cnt[x] += cnt[v];} } } int main() { n = read(); for(int i = 1;i <= n;++ i) { scanf("%s",a); loc[i] = insert(a); } get_fail(); for(int i = 1;i <= sz;++ i) { add_edge(fail[i],i); } dfs(0); for(int i = 1;i <= n;++ i) { printf("%d\n",cnt[loc[i]]); } return 0; }
#include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxn = 1000001; int n; char s[maxn]; int ans=0; struct Aho_Corasick_automato{ int sz; int ch[maxn][26]; int val[maxn]; int last[maxn]; int fail[maxn]; int num; void init() { memset(ch[0],0,sizeof(ch[0])); sz=1; } void insert(char *s) { int len=strlen(s); int u=0; for(int i=0; i<len; ++i) { int v=(s[i]-'a'); if(!ch[u][v]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][v]=sz++; } u=ch[u][v]; } val[u]++; } void get_fail() { fail[0]=0; queue<int>que; for(int i=0; i<26; i++) { int u=ch[0][i]; if(u) { fail[u]=0; que.push(u); } } while(!que.empty()) { int u=que.front(); que.pop(); for(int i=0; i<26; i++) { int v=ch[u][i]; if(!v) { ch[u][i]=ch[fail[u]][i]; continue; } que.push(v); int k=fail[u]; fail[v]=ch[k][i]; last[v]=val[fail[v]] ? fail[v] : last[fail[v]]; } } } void work(int x) { if(val[x]) { ans+=val[x]; val[x]=0; work(last[x]); } } void find(char *s) { int len=strlen(s); int u=0; for(int i=0; i<len; i++) { int v=(s[i]-'a'); if(!ch[u][v])u=fail[u]; while(u&&!ch[u][v]) u=fail[u]; u=ch[u][v]; if(val[u]) work(u); else if(last[u]) work(last[u]); } } } ac; int main() { scanf("%d",&n); ac.init(); for(int i=1; i<=n; i++) { scanf("%s",s); ac.insert(s); } ac.get_fail(); scanf("%s",s); ac.find(s); printf("%d\n",ans); return 0; }
虚树
#include<cstdio> #include<cstring> #include<algorithm> inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar(); } while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); return x * f; } const int maxn = 300007; int n; struct node { int v,next; } edge[maxn << 1],e[maxn << 1]; int head[maxn],num,h[maxn],num1,deep[maxn]; inline void add(int u,int v) { if(u == v) return; e[++ num1].v = v;e[num1].next = h[u];h[u] = num1; } inline void add_edge(int u,int v ) { edge[++ num].v = v;edge[num].next = head[u];head[u] = num; } int dfn[maxn],cnt = 0,dad[maxn][20],size[maxn]; void dfs(int x,int fa) { size[x] = 1; dfn[x] = ++ cnt; deep[x] = deep[fa] + 1; dad[x][0] = fa; for(int i = 0;dad[x][i];++ i) dad[x][i + 1] = dad[dad[x][i]][i]; for(int i = head[x];i;i = edge[i].next ) { int v = edge[i].v; if(v == fa) continue; dfs(v,x); size[x] += size[v]; } } int lca(int x,int y) { if(deep[x] > deep[y]) std::swap(x,y); for(int i = 18;i >= 0;-- i)if(deep[x] <= deep[dad[y][i]]) y = dad[y][i]; if(x == y) return x; for(int i = 18;i >= 0;-- i) if(dad[x][i] != dad[y][i])x = dad[x][i],y = dad[y][i]; return x == y ? x : dad[x][0]; } inline bool cmp(int x,int y) {return dfn[x] < dfn[y];} int c[maxn],rem[maxn],Dfn,bel[maxn]; int dis(int x,int y) { return deep[x] + deep[y] - 2 * deep[lca(x,y)]; } void get_fri(int x) { c[++ Dfn] = x;rem[x] = size[x]; for(int i = h[x];i;i = e[i].next ) { int v = e[i].v; get_fri(v); if(!bel[v]) continue; int t1 = dis(bel[v],x),t2 = dis(bel[x],x); if((t1 == t2 && bel[v] < bel[x]) || t1 < t2 || !bel[x]) bel[x] = bel[v]; } } void get_sec(int x) { for(int i = h[x];i;i = e[i].next) { int v = e[i].v; int t1 = dis(bel[x],v),t2 = dis(bel[v],v); if((t1 == t2 && bel[v] > bel[x]) || t1 < t2 || !bel[v])bel[v] = bel[x]; get_sec(v); } } int dp[maxn]; void divide(int a,int b) { int x = b,mid = b; for(int i = 18;i >= 0;-- i) if(deep[dad[x][i]] > deep[a]) x = dad[x][i]; rem[a] -= size[x]; if(bel[a] == bel[b]) { dp[bel[a]] += size[x] - size[b]; return; } for(int i = 18;i >= 0;-- i) { if(deep[dad[mid][i]] <= deep[a]) continue; int t1 = dis(bel[a],dad[mid][i]),t2 = dis(bel[b],dad[mid][i]); if(t1 > t2 || (t1 == t2 && bel[b] < bel[a]))mid = dad[mid][i]; } dp[bel[a]] += size[x] - size[mid]; dp[bel[b]] += size[mid] - size[b]; } int htmp[maxn],stack[maxn],H[maxn]; void solve(int k = 0) { int top;memset(h,0,sizeof h); top = Dfn = 0; k = read(); for(int i = 1;i <= k;++ i) htmp[i] = H[i] = read(); for(int i = 1;i <= k;++ i) bel[H[i]] = H[i] ; std::sort(H + 1,H + k + 1,cmp); stack[++ top] = 1; for(int i = 1;i <= k;++ i) { int x = H[i],f = lca(stack[top],x); while("tle") { if(deep[f] >= deep[stack[top - 1]]) { add(f,stack[top --]); if(stack[top] != f) stack[++ top] = f; break; } add(stack[top - 1],stack[top]);top --; } if(stack[top] != x) stack[++ top] = x; } while(top - 1) add(stack[top - 1],stack[top]),top --; get_fri(1); get_sec(1); for(int i = 1;i <= Dfn;++ i) for(int j = h[c[i]];j;j = e[j].next) { divide(c[i],e[j].v); } for(int i = 1;i <= Dfn;++ i) dp[bel[c[i]]] += rem[c[i]]; for(int i = 1;i <= k;++ i) printf("%d ",dp[htmp[i]]);puts(""); for(int i = 1;i <= Dfn;++ i) dp[c[i]] = bel[c[i]] = H[c[i]] = rem[c[i]] = 0; num1 = 0; } int main() { n = read(); for(int u,v,i = 1;i < n;++ i) { u = read(),v = read(); add_edge(u,v);add_edge(v,u); } dfs(1,0); int q = read() ; for(;q --;) solve(); return 0; }
排序
快排+求k大值
int qsort(int *a,int l,int r) { int tmp = a[l],pos = l; int i = l, j = r; while (i<j) { while (i<j&&a[j]>tmp) j--; if (i<j) { a[pos] = a[j]; pos = j; } while (i<j&&a[i]<tmp) i++; if (i<j) { a[pos] = a[i]; pos = i; } } a[pos] = tmp; return pos; } int findkth(int *a,int n,int k) { int l = 0,r = n-1; while (1) { int pos = qsort(a,l,r); if (pos==n-k) return a[pos]; else if (pos<n-k) l = pos+1; else r = pos-1; } } 快速排序求第k大的数
归并+求逆序对
#include<cstdio> int n,ans; int a[500100],b[500100]; //a原数组,b暂存数组 void merge_sort(int l,int r) //归并 { if (l==r) return ; //一个数不用排序 int m = (l+r)>>1; merge_sort(l,m); //排序左边 merge_sort(m+1,r); //排序右边 int i = l, j = m+1, k = l ; //i左边最小的位置,j右边最小的位置 while (i<=m && j<=r) if (a[i]<=a[j]) b[k++] = a[i++]; else ans += m-i+1, b[k++] = a[j++]; //加入右半段时,逆序对数增加 while (i<=m) b[k++] = a[i++]; //加入左边剩余的数 while (j<=r) b[k++] = a[j++]; //加入右边剩余的数 for (i=l; i<=r; ++i) a[i] = b[i]; //从暂存数组中赋值 } int main() { scanf("%d",&n); for (int i=1; i<=n; ++i) scanf("%d",&a[i]); merge_sort(1,n); printf("%d",ans); return 0; }
数学
组合数递推
C[1][0] = C[1][1] = 1; for (int i=2; i<=N; i++) { C[i][0] = 1; for (int j=1; j<=N; j++) C[i][j] = C[i-1][j]+C[i-1][j-1]; }
线性筛求莫比乌斯函数(mu)
void get() { int n = 100; mu[1]=1; for(int i=2;i<=n;i++) { if(!ol[i])prime[++num]=i,cout<<i<<" ",mu[i]=-1; for(int j=1;j<=num&&j*prime[i]<=n;j++) { ol[i*prime[j]]=1; if((i%prime[j])==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } cout<<num<<endl; }
根n求欧拉函数
int getphi(int x){ int ret=1; for(int i=1;prime[i]*prime[i]<=x;i++){ if(x%prime[i]==0) { ret*=prime[i]-1; x/=prime[i]; while(x%prime[i]==0) x/=prime[i],ret*=prime[i]; } } if(x>1) ret*=x-1; return ret; }
矩阵乘法(fib
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int mod = 1e9+7; const int N = 2; struct Matrix{ int a[N][N]; Matrix(){ this->clear(); } void clear(){ memset(a,0,sizeof(a)); } void setone(){ this->clear(); for (int i=0; i<N; ++i) a[i][i] = 1; } Matrix operator * (const Matrix &x) const { Matrix c; for (int k=0; k<N; k++) for (int i=0; i<N; ++i) for (int j=0; j<N; ++j) c.a[i][j] = (c.a[i][j]+1ll*a[i][k]*x.a[k][j])%mod; return c; } }; int fibn(int n) { Matrix x,s; x.a[0][0] = x.a[0][1] = x.a[1][0] = 1; s.setone(); for (; n; n>>=1) { if (n&1) s = s*x; x = x*x; } return (s.a[0][0]+s.a[0][1])%mod; } int main() { int n; while (~scanf("%d",&n)) { if (n==1||n==2) puts("1"); else printf("%d\n",fibn(n-2)); } return 0; }
逆元相关:
线性求逆元
#include<cstdio> #include<algorithm> #define LL long long LL inv[3000053]; //int inv[MAXN]; void INV(int a,int p) { inv[1] = 1; for (int i=2; i<=a; ++i) inv[i] = (LL)((p-(p/i)%p)%p*inv[p%i])%p; } int main() { int n,p; scanf("%d%d",&n,&p); INV(n,p); for(int i=1;i<=n;++i) printf("%d\n",inv[i]); return 0; }
#include<cstdio> #include<algorithm> #define LL long long LL inv[3000053]; //int inv[MAXN]; void INV(int a,int p) { inv[1] = 1; for (int i=2; i<=a; ++i) inv[i] = (LL)((p-(p/i)%p)%p*inv[p%i])%p; } int main() { int n,p; scanf("%d%d",&n,&p); INV(n,p); for(int i=1;i<=n;++i) printf("%d\n",inv[i]); return 0; }
高斯消元
void gauss() { int t; for(int i=1;i<=n;++i) { t=i; for(int j=i+1;j<=n;++j) if(loc[j][i]>loc[t][i]) t=j; if(t!=i) for(int j=i;j<=n+1;++j) std::swap(loc[t][j],loc[i][j]); for(int j=i+1;j<=n;++j) { double tmp=loc[i][i]/loc[j][i]; for(int k=i+1;k<=n+1;++k) loc[j][k]=loc[i][k]-tmp*loc[j][k]; } } for(int i=n;i>=1;--i) { for(int j=i+1;j<=n;++j) loc[i][n+1]-=x[j]*loc[i][j]; x[i]=loc[i][n+1]/loc[i][i]; } }
扩展欧几里得求逆元
#include<cstdio> int exgcd(int a,int b,int &x,int &y) { if (b==0) { x = 1; y = 0; return a; } int r = exgcd(b,a%b,x,y); int tmp = x; x = y; y = tmp-a/b*y; return r; } int main() { //gcd(a,p)==1 int a,p,r,x,y; while (scanf("%d%d",&a,&p)!=EOF) { r = exgcd(a,p,x,y); printf("%d",(x%p+p)%p); } return 0; }
数论bsgs+exgcd+q_pow
1 #include<cstdio> 2 #include<map> 3 #include<cmath> 4 using namespace std; 5 6 typedef long long LL; 7 int T,L; 8 9 LL qpow(LL a,LL p,LL mod) 10 { 11 LL base=a; 12 LL sum=1; 13 while(p!=0) 14 { 15 if(p&1) 16 sum=(sum*base)%mod; 17 base=(base*base)%mod; 18 p>>=1; 19 } 20 return sum; 21 } 22 23 void work1() 24 { 25 LL y,z,p; 26 scanf("%lld%lld%lld",&y,&z,&p); 27 printf("%lld\n",qpow(y,z,p)%p); 28 return ; 29 } 30 31 32 void exgcd(int a,int b,LL &d,LL &x,LL &y) 33 { 34 if(!b){d=a;x=1;y=0;return ;} 35 exgcd(b,a%b,d,y,x); 36 y-=x*(a/b); 37 } 38 LL gcd(LL a,LL b) 39 { 40 if(!b) return a; 41 return gcd(b,a%b); 42 } 43 void work2() 44 { 45 LL a,b,y,z,x,d,mod; 46 scanf("%lld%lld%lld",&y,&z,&mod); 47 a=y; 48 b=-mod; 49 d=gcd(a,b); 50 if(z%d) 51 { 52 printf("Orz, I cannot find x!\n"); 53 return ; 54 } 55 a/=d;b/=d;z/=d; 56 exgcd(a,b,d,x,y); 57 x*=z;x%=b; 58 while(x<0) x+=b; 59 printf("%lld\n",x); 60 } 61 62 63 map<LL,LL>mp; 64 void work3() 65 { 66 mp.clear(); 67 LL y,z,q,p; 68 scanf("%lld%lld%lld",&y,&z,&p); 69 y%=p; 70 if(!y&&!z) 71 { 72 puts("1");return ; 73 } 74 if(!y) 75 { 76 printf("Orz, I cannot find x!\n"); 77 return; 78 } 79 LL pos=ceil(sqrt(p)); 80 LL ans; 81 for(LL i=0;i<=pos;i++) 82 { 83 if(i==0) 84 { 85 ans=z%p; 86 mp[ans]=1; 87 continue; 88 } 89 ans=(ans*y)%p; 90 mp[ans]=i; 91 } 92 ans=1; 93 LL t=qpow(y,pos,p); 94 for(LL i=1;i<=pos;i++) 95 { 96 ans=(ans*t)%p; 97 if(mp[ans]) 98 { 99 LL b=i*pos-mp[ans]; 100 printf("%d\n",(b%p+p)%p); 101 return ; 102 } 103 } 104 printf("Orz, I cannot find x!\n"); 105 } 106 int main() 107 { 108 scanf("%d%d",&T,&L); 109 if(L==1) 110 for(int i=1;i<=T;i++) 111 work1(); 112 if(L==2) 113 for(int i=1;i<=T;i++) 114 work2(); 115 if(L==3) 116 for(int i=1;i<=T;i++) 117 work3(); 118 return 0; 119 }
同于方程组:
中国剩余定理
/*long long gcd(LL a,LL b) { return b==0?a:gcd(b,a%b); }*/ #include<cstdio> #define ll long long //扩展欧几里得算法 void gcd(ll a,ll b,ll &d,ll &x,ll &y) { if(b==0){ d=a; x=1,y=0; } else{//else不能省略 gcd(b,a%b,d,y,x); y-=(a/b)*x; } } //中国剩余定理 ll China(int n,ll *m,ll *a) { ll M=1,d,y,x=0; for(int i=0;i<n;i++) M*=m[i]; for(int i=0;i<n;i++){ ll w=M/m[i]; gcd(m[i],w,d,d,y); x=(x+y*w*a[i])%M; } return (x+M)%M; } ll m[15],a[15]; int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lld%lld",&m[i],&a[i]); printf("%lld",China(n,m,a)); }
扩展欧几里得解法
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define LL long long LL a[6],r[6]; int n; LL exgcd(LL a,LL b,LL &x,LL &y) { if(b==0) {x=1,y=0;return a;} LL tmp=exgcd(b,a%b,y,x); y-=a/b*x; return tmp; } LL solve() { LL M=a[1],R=r[1],x,y,d; for(int i=2;i<=4;i++) { d=exgcd(M,a[i],x,y); if((R-r[i])%d!=0) return -1; x=(R-r[i])/d*x%a[i]; R-=x*M; M=M/d*a[i]; R%=M; } return (R%M+M)%M; } int main() { for(int i=1; i<=4; i++) scanf("%lld%lld",&a[i],&r[i]); printf("%lld\n",solve()); return 0; }
矩阵快速幂
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define LL long long int n;LL k; const int mod = 1e9+7; struct Matrix { LL a[107][107]; Matrix() { std::memset(a,0,sizeof a); } Matrix operator * (const Matrix & y)const { Matrix ans; for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) { for(int k=1;k<=n;++k) { ans.a[i][j]=(ans.a[i][j]+((a[i][k]%mod)*(y.a[k][j]%mod)))%mod; } } } return ans; } }pre,ans; void pow(LL k) { for(int i=1;i<=n;++i) ans.a[i][i]=1; while(k) { if(k&1) ans=ans*pre; pre=pre*pre; k>>=1; } for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) { printf("%lld ",ans.a[i][j]); } puts(""); } return ; } int main() { scanf("%d%lld",&n,&k); for(int i=1;i<=n;++i) { for(int j=1;j<=n;++j) { scanf("%d",&pre.a[i][j]); } } pow(k); return 0; }
高消异或
#include<bits/stdc++.h> using namespace std; // 每天好心情从namespace开始 const int maxn = 157; #define LL long long inline LL read() { LL x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = - 1; c = getchar();} while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); return x * f; } int n; const int mod = 1000000007; long long A[100007]; int prime[100007],is[100007],num = -1; void getprime() { for(int i = 2;i <= 2000;++ i) { if(!is[i]) prime[++ num] = i; for(int j = 0;j <= num && prime[j] * i <= 2000;++ j) { is[i * prime[j]] = 1; if(i % prime[j] == 0) break; } } } bitset<330>a[305]; int guass(int equ,int var) { int r,c,t,j = 0; for(r = c = 0;r < equ && c < var;++ r, ++c) { for(t = r;t < equ;++ t) if(a[t][c]) break; if(t == equ) { r --;continue; } else swap(a[t],a[r]); for(int i = r + 1; i < equ;++ i) if(a[i][c]) a[i] ^= a[r]; } return var - r; } int solve() { for(int i = 0; i < 305; i++) a[i].reset(); for(int i = 0;i < n;++ i) for(int j = 0;j <= num;++ j) { LL tmp = A[i]; if(tmp % prime[j] == 0) { bool flag = 0; while(tmp % prime[j] == 0) { tmp /= prime[j]; flag ^= 1; } a[j][i] = flag; } } int zyy = guass(num + 1,n); LL ret = 1; for(int i = 1;i <= zyy;++ i)ret <<= 1,ret %= mod; return ret - 1; } int main() { getprime(); int t = read(); int cas = 0; while(t --) { ++ cas; printf("Case #%d:\n",cas); n = read(); for(int i = 0;i < n;++ i) A[i] = read(); printf("%d\n",solve()); } return 0; }
反演
#include <queue> #include <cstdio> #include <algorithm> inline int read() { int x = 0; char c = getchar(); while(c < '0' || c > '9')c = getchar(); while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); return x; } const int mod = (1 << 31); const int maxn = 100007; int p[maxn],mu[maxn],mx; bool vis[maxn]; struct node { int n,m,a,id; bool operator < (const node & k)const { return a < k.a; } } q[maxn]; std::pair<int,int>F[maxn]; void getmu() { int size = mx,num = 0; mu[1] = 1; for(int i = 2;i <= size;++ i) { if(!vis[i]) p[++ num] = i,mu[i] = -1; for(int j = 1;j <= num && i * p[j] <= size;++ j) { vis[i * p[j]] = true; if(i % p[j] == 0) { mu[i * p[j]] = 0; break; } mu[i * p[j]] = -mu[i]; } } for(int i = 1;i <= size;++ i) for(int j = i;j <= size;j += i) F[j].first += i; for(int i = 1;i <= size;++ i)F[i].second = i; } int ans[maxn]; #define lowbit(x) x&(-x) int bit[maxn << 1]; void add(int x,int num) { for(int i = x;i <= mx; i += lowbit(i))bit[i] += num; } int query(int x) { int ret = 0; for(int i = x;i; i -= lowbit(i)) ret += bit[i]; return ret; } void solve(int x) { int n = q[x].n,m = q[x].m; for(int i = 1,j;i <= q[x].n;i = j + 1) { j = std::min(m / (m / i),n / (n/i)); ans[q[x].id] += (n / i) * (m / i) * (query(j) - query(i - 1)); } } int main() { int k = read(); for(int i = 1;i <= k;++ i) { q[i].n = read(),q[i].m = read(),q[i].a = read(); if(q[i].n > q[i].m) std::swap(q[i].n,q[i].m); q[i].id = i; mx = std::max(mx,q[i].n); } getmu(); std::sort(q + 1,q + k + 1); std::sort(F + 1,F + mx + 1); for(int i = 1,now = 0;i <= k;++ i) { for(;now + 1 <= mx && F[now + 1].first <= q[i].a;) { now ++; for(int j = F[now].second;j <= mx;j += F[now].second) { //printf("%d\n",now); add(j,F[now].first * mu[j / F[now].second]); } } solve(i); } //printf("%d\n",mod); for(int i = 1;i <= k;++ i) { printf("%d\n",ans[i] & 0x7fffffff ); } return 0; }
杂七杂八算法
二分查找+lower_bound(有序序列
int binary_search(int x,int y,int c) { int l,r,mid; l = x; r = y; while (l<r) { mid = (l+r)>>1; if (c<=a[mid]) r = mid; else l = mid+1; } return l; } /*------------------------------------*/ int find(int l,int r,int x) { while (l<=r) { int mid = (l+r)>>1; if (a[mid]<=x) l = mid+1; else r = mid-1; } return l; }
lower_bound
lower_bound(a+x,a+y+1,c)-a;
莫队
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> using namespace std; const int N = 100010; int n,m,num,a[N]; struct data{ int l,r,id,block; }q[N]; int cnt[N],ans[N]; bool cmp(data a,data b) { if(a.block==b.block) return a.r<b.r; return a.block < b.block; } int tmp; /*void add(int x) { cnt[a[x]]++; if(cnt[a[x]]==1)tmp++; } void del(int x) { cnt[a[x]]--; if(!cnt[a[x]])tmp--; }*/ void Solve() { int l=1,r=0; for(int i=1;i<=m;i++) { while(l<q[i].l) del(l),l++; while(l>q[i].l) l--,add(l); while(r<q[i].r) r++,add(r); while(r>q[i].r) del(r),r--; ans[q[i].id]=tmp; } } int main() { cin>>n; num=sqrt(n); for(int i=1;i<=n;i++)cin>>a[i]; cin>>m; for(int i=1;i<=m;i++) { cin>>q[i].l>>q[i].r; q[i].id=i; q[i].block=(q[i].l-1)/num+1; } sort(q+1,q+m+1,cmp); Solve(); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }
分块的构造??(假的
inline void divide(int x) { for(int i=1;i<=x;i++) left[i]=right[i-1]+1,right[i]=i*x; right[x]=n; for(int i=1;i<=x;i++) for(int j=left[i];j<=right[i];j++) belong[j]=i; for(int i=n;i>=1;i--) { if(where[i]>right[belong[i]])out[i]=1; else out[i]=out[where[i]]+1,where[i]=where[where[i]]; } } inline void query(int x) { int ans=0; while(x<=n) { ans+=out[x],x=where[x]; } printf("%d\n",ans); } inline void modify(int x,int y) { int i,j; int tmp=belong[x],l=left[tmp],r=right[tmp]; a[x]=x+y; if(a[x]>r)out[x]=1,where[x]=a[x]; else out[x]=out[a[x]]+1,where[x]=where[a[x]]; for(i=x-1;i>=l;i--) { if(a[i]<=x) out[i]=out[a[i]]+1,where[i]=where[a[i]]; } } n=read(); int x=sqrt(n); for(int i=1;i<=n;i++) a[i]=read(),where[i]=i+a[i],a[i]=where[i];
点分治
#include<cstdio> #include<algorithm> inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();} while(c <= '9' &&c >= '0')x = x * 10 + c - '0',c = getchar(); return x * f; } const int maxw = 2000007; const int maxn = 160000 + 10000 + 7; struct Query { int x,y,type,w,aid; Query(int Type = 0,int X = 0,int Y = 0,int W = 0,int Aid = 0) : type(Type),x(X),y(Y),w(W),aid(Aid){}; bool operator < (const Query & A)const { return x == A.x ? type < A.type : x < A.x; } } ; Query query[maxw / 10 + 7]; Query tmp[maxw / 10 + 7]; int ans[maxn],maxy; namespace BIT { #define lowbit(x) (x & (-x)) int sum[maxw << 1]; void add(int idx,int val) { //puts("1"); for(;idx <= maxy; idx += lowbit(idx)) sum[idx] += val; } int query(int idx) { int ret = 0; for(;idx;idx -= lowbit(idx)) ret += sum[idx]; return ret; } void clear(int idx) { for(;idx <= maxy;idx += lowbit(idx)) { if(sum[idx]) sum[idx] = 0; else break; } } } void cdq(int l,int r) { if(r - l <= 1) return; int mid = l + r >> 1; cdq(l,mid);cdq(mid,r); int p = l,q = mid,cnt = l; for(;p < mid && q < r;) { if(query[p] < query[q]) { if(query[p].type == 1) BIT::add(query[p].y,query[p].w); tmp[cnt ++] = query[p ++]; } else { if(query[q].type == 2) ans[query[q].aid] += query[q].w * BIT::query(query[q].y); tmp[cnt ++] = query[q ++]; } } while(p < mid) tmp[cnt ++] = query[p ++]; while(q < r) { if(query[q].type == 2) ans[query[q].aid] += query[q].w * BIT::query(query[q].y); tmp[cnt ++] = query[q ++]; } for(int i = l;i < r;++ i) { BIT::clear(tmp[i].y); query[i] = tmp[i]; } } int qid = 0,aid = 0; int main() { int type = read(), n = read(); maxy = n; for(int x,y,x1,y1,val;;) { type = read(); if(type == 3) break; if(type == 1) {x = read(),y = read(),val = read();query[qid ++] = Query(1,x,y,val,0); } if(type == 2) { x = read(),y = read(),x1 = read(),y1 = read(); query[qid ++] = Query(2,x - 1,y - 1,1,aid); query[qid ++] = Query(2,x - 1,y1,-1,aid); query[qid ++] = Query(2,x1,y - 1,-1,aid); query[qid ++] = Query(2,x1,y1,1,aid); aid ++; } } cdq(0,qid); for(int i = 0;i < aid;++ i) printf("%d\n",ans[i]); return 0; }
模拟退火
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> const int maxn = 100007; double x[maxn],y[maxn],w[maxn]; int n;double ansx,ansy,nowx,nowy,Ans = 1.0 * 1e18; double calc(double X,double Y) { double ret = 0; for(int i = 1;i <= n;++ i) ret += w[i] * sqrt((X - x[i]) * (X - x[i]) + (Y - y[i]) * (Y - y[i])); if(ret < Ans) Ans = ret,ansx = X,ansy = Y; return ret; } double Random() {return (double) rand() / RAND_MAX;} void SA(double T) { nowx = ansx,nowy = ansy; double tmpx ,tmpy; while(T > 0.001) { tmpx = nowx + T * (Random() * 2 - 1); tmpy = nowy + T * (Random() * 2 - 1); double DE = calc(nowx,nowy) - calc(tmpx,tmpy); if(DE > 0 || Random() <= exp(DE/T)) nowx = tmpx,nowy = tmpy; T *= 0.98; } for(int i = 1;i <= 1000;++ i) { tmpx = ansx + T * (Random() * 2 - 1) ; tmpy = ansy + T * (Random() * 2 - 1) ; calc(tmpx,tmpy); } } int main() { srand(19260817); scanf("%d",&n); for(int i = 1;i <= n;++ i) scanf("%lf%lf%lf",x + i,y + i,w + i), ansx += x[i],ansy += y[i]; ansx /= n;ansy /= n; //printf("%lf %lf\n",Ans,ansy); SA(40000001); printf("%.3lf %.3lf",ansx,ansy); return 0; }
图论相关
lca相关
链剖求lca
#include <cstdio> #include <cstdlib> #define maxm 200010 struct edge{int to,len,next;}E[maxm]; int cnt,last[maxm],fa[maxm],top[maxm],deep[maxm],siz[maxm],son[maxm],val[maxm]; void addedge(int a,int b,int len=0) { E[++cnt]=(edge){b,len,last[a]},last[a]=cnt; } void dfs1(int x) { deep[x]=deep[fa[x]]+1;siz[x]=1; for(int i=last[x];i;i=E[i].next) { int to=E[i].to; if(fa[x]!=to&&!fa[to]){ val[to]=E[i].len; fa[to]=x; dfs1(to); siz[x]+=siz[to]; if(siz[son[x]]<siz[to])son[x]=to; } } } void dfs2(int x) { if(x==son[fa[x]])top[x]=top[fa[x]]; else top[x]=x; for(int i=last[x];i;i=E[i].next)if(fa[E[i].to]==x)dfs2(E[i].to); } void init(int root){dfs1(root),dfs2(root);} int query(int x,int y) { for(;top[x]!=top[y];deep[top[x]]>deep[top[y]]?x=fa[top[x]]:y=fa[top[y]]); return deep[x]<deep[y]?x:y; } int n,m,x,y,v; int main() { scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y);addedge(x,y,v);addedge(y,x,v); } init(1); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); printf("%d\n",query(x,y)); } return 0 ; }
倍增lca
//lca 倍增 2 /*倍增法 3 4 首先如果两个点的深度如果不同, 5 将深度较大的点跳到与深度较小的点一样的深度, 6 再同时向上跳,首次相遇时即为最近公共祖先。 7 */ #include<cstdio> using namespace std; const int N=10015; vector<int>vec[N]; int n,m,t,p,q; int dad[N][N],deep[N]; void dfs(int x) { deep[x]=deep[dad[x][0]]+1; for(int i=0;dad[x][i];i++) { dad[x][i+1]=dad[dad[x][i]][i];//滚动赋值,如果存在节点x的第2^i的祖先那么节点x的第2^(i+1)个祖先=节点x的2^i的祖先再往前走2^i个祖先 } for(int i=0;i<vec[x].size();i++) if(!deep[vec[x][i]]) { dad[vec[x][i]][0]=x; dfs(vec[x][i]); } } int lca(int x,int y) { if(deep[x]>deep[y])swap(x,y); for(int i=20;i>=0;i--) { if(deep[dad[y][i]]>=deep[x])y=dad[y][i]; }//自己跳 if(x==y)return x; for(int i=20;i>=0;i--) if(deep[dad[x][i]]!=deep[dad[y][i]]) { x=dad[x][i]; y=dad[y][i]; }//一起跳 return dad[x][0]; } int main() { scanf("%d%d%d",&n,&m,&t);//n个点,m条边,t个访问 int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); vec[x].push_back(y); vec[y].push_back(y); } dfs(1); while(t--) { scanf("%d%d",&p,&q); printf("%d\n",lca(p,q)); } }
tarjan+缩点
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n,m,topp; #define N 100006 struct sta{ int sz[100001]; int top(){return sz[topp];} void push(int x){sz[++topp]=x;} void pop(){if(topp>0)topp--;} }stack; struct node{ int v,next; }edge[N*5];int head[N],num; int dfn[N],low[N],color[N];bool vis[N]; void add_edge(int x,int y) { edge[++num].v=y;edge[num].next=head[x];head[x]=num; } int cnt; void tarjan(int x) { dfn[x]=low[x]=++num; stack.push(x); vis[x]=1; for(int i=head[x];i;i=edge[i].next) { int v=edge[i].v; if(!dfn[v]) { tarjan(v); low[x]=min(low[x],low[v]); } else if(vis[v])low[x]=min(low[x],dfn[v]); } if(dfn[x]==low[x]) { ++cnt; int r; do{ r=stack.top(); color[r]=cnt; vis[r]=0; stack.pop(); }while(r!=x); } return ; } int main() { scanf("%d%d",&n,&m); int a,b; for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b);add_edge(a,b); } num=0; for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) { for(int j=head[i];j;j=edge[j].next) { int v=edge[j].v; if(color[i]!=color[v]) { vis[color[v]]=1; } } } int ans=0; for(int i=1;i<=cnt;i++) if(!vis[i]) ans++; printf("%d\n",ans); return 0; }
树剖
#include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' ||c > '9'){if(c == '-')f= -1; c = getchar();} while(c <= '9' &&c >= '0')x = x * 10 + c- '0',c = getchar(); return x * f; } #define int long long const int maxn = 200007; int n,m,val[maxn]; struct node { int u,v,next; } edge[maxn << 1]; int head[maxn],num; inline void add_edge(int u,int v) { edge[++ num].v = v; edge[num].next = head[u];head[u] = num ; } int fa[maxn],deep[maxn],siz[maxn],son[maxn]; void dfs1(int x) { deep[x] = deep[fa[x]] + 1;siz[x] = 1; for(int i = head[x];i ;i = edge[i].next) { int v = edge[i].v; if(deep[v]) continue; fa[v] = x; dfs1(v); siz[x] += siz[v]; if(siz[v] > siz[son[x]] || !son[x]) son[x] = v; } } int pos[maxn],_pos,sop[maxn],top[maxn]; void dfs2(int x,int topfa) { top[x] = topfa;pos[x] = ++_pos;sop[_pos] = x; if(!son[x]) return ; dfs2(son[x],topfa); for(int i = head[x];i;i = edge[i].next) { int v = edge[i].v; if(v == son[x] || v == fa[x]) continue; dfs2(v,v); } } #define lc rt << 1 #define rc rt << 1 | 1 int sum[maxn << 2],tag[maxn << 2]; inline void update(int rt) {sum[rt] = sum[lc] + sum[rc]; } void build(int rt,int l,int r) { if(l == r) { sum[rt] = val[sop[l]];return ; } int mid = l + r >> 1; build(lc,l,mid); build(rc,mid + 1,r); return update(rt); } inline void pushdown(int rt,int l,int r) { int mid = l + r >> 1; tag[lc] += tag[rt];tag[rc] += tag[rt]; sum[lc] += (mid - l + 1) * tag[rt]; sum[rc] += (r - mid) * tag[rt]; tag[rt] = 0; } int T_query(int rt,int l,int r,int tl,int tr ){ if(l >= tl && r <= tr) return sum[rt]; if(tag[rt] != 0) pushdown(rt,l,r); int mid = l + r >> 1,Ret = 0 ; if(tl <= mid) Ret += T_query(lc,l,mid,tl,tr); if(tr > mid) Ret += T_query(rc,mid + 1,r,tl,tr); return Ret; } void T_modify(int rt,int l,int r,int tl,int tr,int a) { if(l >= tl && r <= tr) { sum[rt] += (r - l + 1) * a; tag[rt] += a; return ; } if(tag[rt] != 0)pushdown(rt,l,r); int mid = l + r >> 1; if(tl <= mid) T_modify(lc,l,mid,tl,tr,a); if(tr > mid) T_modify(rc,mid + 1,r,tl,tr,a); update(rt); } int Q(int x) { int ret = 0 ; for(;top[x] != 1;x = fa[top[x]]) ret += T_query(1,1,n,pos[top[x]],pos[x]); ret += T_query(1,1,n,pos[top[x]],pos[x]); return ret; } void M1(int x,int a) { T_modify(1,1,n,pos[x],pos[x],a); } void M2(int x,int a) { T_modify(1,1,n,pos[x],pos[x] + siz[x] - 1,a); } main() { n = read(),m = read(); for(int i = 1;i <= n;++ i) val[i] = read(); for(int u,v,i = 1;i < n;++ i) { u = read(); v = read(); add_edge(u,v); add_edge(v,u); } dfs1(1); dfs2(1,1); build(1,1,n); for(int type,x,a;m --;) { type = read(); if(type == 1) { x = read(); a = read(); M1(x,a); } else if(type == 2) { x = read(); a = read(); M2(x,a); } else { x = read(); printf("%lld\n",Q(x)) ; } } return 0; }
割边
void tarjan(int u,int fa) { dfn[u] = low[u] = ++tn; for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to; if (!dfn[v]) { tarjan(v,u); low[u] = min(low[u],low[v]); if (low[v] > dfn[u]) { printf("%d %d\n",u,v); } } else if (dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]); } }
割点
void tarjan(int u,int fa) { low[u] = dfn[u] = ++tn; int cnt_son = 0; for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to; if (!dfn[v]) { cnt_son++; tarjan(v,u); low[u] = min(low[u],low[v]); if (low[v] >= dfn[u]) iscut[u] = true; } else if (dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]); } if (fa<0 && cnt_son==1) iscut[u] = false; }
边双连通分量
写法1
void tarjan(int u,int fa) { dfn[u] = low[u] = ++tn; st[++top] = u; vis[u] = true; for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to; if (!dfn[v]) { tarjan(v); low[u] = min(low[u],low[v]); } else if (vis[v] && v!=fa) low[u] = min(low[u],dfn[v]); } if (dfn[u] == low[u]) { ++cnt; do { vis[st[top]] = false; bel[st[top]] = cnt; top--; } while (st[top+1] != u); } }
写法2
void tarjan(int u,int fa) { dfn[u] = low[u] = ++tn; for (int i=head[u]; i; i=e[i].nxt) { int v = e[i].to; if (!dfn[v]) { tarjan(v,u); low[u] = min(low[u],low[v]); } else if (dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]); } }
堆优化dijkstra
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define INF 0x3f3f3f3f #define N 1020 int n,m; int head[N]; int dis[N]; struct nnode{ int v;int w,next; }edge[N*N/2]; struct node{ int v,dis; friend bool operator < (node a,node b){ return a.dis>b.dis; } }cur; priority_queue<node>q; int read() { int x=0,f=1; char c; while (c<'0' || c>'9') {if(c=='-')f = -1;c = getchar();} while (c>='0' && c<='9')x=x*10+c-'0',c=getchar(); return x*f; } int num = 0; void add_edge(int x,int y,int w) { edge[num].v=y; edge[num].w=w; edge[num].next=head[x]; head[x]=num++; } int pre_now[N]; int pre[N]; int Dijkstra(int p,int tp) { //memset (head,-1,sizeof -1); memset (dis,0x3f,sizeof dis); dis[1] = 0; q.push(node{1,0}); while(!q.empty()) { cur = q.top(); q.pop(); if(dis[cur.v]<cur.dis)continue; int u = cur.v; for (int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].v; if((v == p && u== tp) || (v==tp && p == u))continue; if(dis[v]>dis[u]+edge[i].w) { dis[v]=dis[u]+edge[i].w; pre_now[v]=u; q.push((node){v,dis[v]}); } } } return dis[n]; } int main() { n = read(); m = read(); for(int i=1;i<=n;i++)head[i]=-1; for (int i = 1; i <= m; i++){ int a,b,c; a = read(),b = read(),c = read(); add_edge(a,b,c);add_edge(b,a,c); } int ans=Dijkstra(0,0); memcpy(pre,pre_now,sizeof(pre)); int k=n; while(k) { int tmp = Dijkstra(pre[k],k); if(tmp!=INF) ans = max(ans,tmp); k = pre[k]; } printf("%d\n",ans); return 0; }
网络流相关
最大流
bool spfa() { memset(lev,-1,sizeof lev); memcpy(cur,head,sizeof head); queue<int>que; que.push(S);lev[S]=0; while(!que.empty()) { int u=que.front();que.pop(); for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; if(edge[i].flow>0&&lev[v]<0) { lev[v]=lev[u]+1;que.push(v); } } } if(lev[T]!=-1)return true; else return false; } int dfs(int now,int flow) { if(now==T)return flow; int rest=0,delta; for(int &i=cur[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==lev[now]+1&&edge[i].flow>0) { delta=dfs(v,min(flow-rest,edge[i].flow)); if(delta) { edge[i].flow-=delta; edge[i^1].flow+=delta; rest+=delta;if(rest==flow)break; } } } if(rest==flow)lev[now]=-1; return rest; } int ans=0; void dinic() { while(spfa()) ans-=dfs(S,INF); }
最小费用最大流
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 4*50000; inline int read() { int x=0,f=1;char c= getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c-'0');c=getchar();} return f*x; } struct node{ int u,v,cost,flow,next; }edge[maxn]; int head[maxn],num=1,n,m,s,t; int min_cost=0,max_flow=0; int dis[maxn],pre[maxn]; bool vis[maxn]; inline void add_edge(int x,int y,int z,int c) { edge[++num].v=y;edge[num].u=x;edge[num].flow=z;edge[num].cost=c;edge[num].next=head[x];head[x]=num; } bool spfa() { memset(dis,0x3f,sizeof dis); memset(vis,0,sizeof vis); vis[s]=1; dis[s]=0; queue<int>que; que.push(s); while(!que.empty()) { int u=que.front(); que.pop(); for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; if(dis[u]+edge[i].cost<dis[v]&&edge[i].flow>0) { dis[v]=edge[i].cost+dis[u]; pre[v]=i; if(!vis[v]) { que.push(v); vis[v]=1; } } } vis[u]=0; } if(dis[t]==0x3f3f3f3f)return 0; else return 1; } void work() { int ma=0x3f3f3f3f; for(int i=t;i!=s;i=edge[pre[i]].u) ma=min(edge[pre[i]].flow,ma); for(int i=t;i!=s;i=edge[pre[i]].u) { edge[pre[i]].flow-=ma; edge[pre[i]^1].flow+=ma; min_cost+=(ma*edge[pre[i]].cost); } max_flow+=ma; } void miku() { while(spfa()) work(); } int main() { n=read(),m=read(),s=read(),t=read(); int a,b,c,d; while(m--) { a=read(),b=read(),c=read(),d=read(); add_edge(a,b,c,d); add_edge(b,a,0,-d); } miku(); printf("%d %d\n",max_flow,min_cost); return 0; }
DP相关
lcs
#include<map> #include<cstdio> #include<algorithm> using namespace std; map<int,int>mp; inline int read() { int x=0;char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar() ; return x; } int n,m,f[200010]; int ef_search(int l,int r,int x) { while(l<r) { int mid=l+r>>1; if(x<=f[mid])r=mid; else l=mid+1; } return l; } int main() { n=read();m=read(); for(int i=1;i<=n;i++) mp[read()]=i; int len=0; for(int pos,i=1;i<=m;i++) { pos=mp[read()]; if(!pos)continue; if(pos>f[len])f[++len]=pos; else { f[ef_search(1,len,pos)]=pos; } } printf("%d\n",len); return 0; }
#include<cstdio> #include<algorithm> #include<vector> using namespace std; const int maxn=505; int n,m,a[maxn],b[maxn]; struct hehe { int num; vector<int>point; } dp[maxn],tmp,ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); for(int i=1;i<=n;i++) scanf("%d",&b[i]); for(int i=1;i<=n;i++) { tmp.num=0; tmp.point.clear(); for(int j=1;j<=n;j++) { if (b[i]>a[j] && dp[j].num>tmp.num) tmp=dp[j]; if (a[j]==b[i]) { dp[j]=tmp; dp[j].num=tmp.num+1; dp[j].point.push_back(a[j]); } } } for(int i=1;i<=n;i++) if (dp[i].num>ans.num) ans=dp[i]; printf("%d\n",ans.num); for (int k=0; k<ans.point.size(); k++) printf("%d ",ans.point[k]); return 0; }
上升
#include<cstdio> #include<iostream> using namespace std; int ans[100000]; int a[100000];int len=1; inline int mid_serch(int x) { int l=0,r=len; while(l<=r) { int mid=(l+r)>>1; if(ans[mid]<a[x])l=mid+1; else r=mid-1; } return l; } int main() { int m; scanf("%d",&m); for(int i=1;i<=m;++i)scanf("%d",a+i); ans[1]=a[1]; for(int i=2;i<=m;++i) { if(a[i]>ans[len]) ans[++len]=a[i]; else { int tmp=mid_serch(i); ans[tmp]=a[i]; } } printf("%d",len); }
多项式
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> inline int read() { int x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c <= '9' && c >= '0')x = x * 10 + c- '0',c = getchar(); return x ; } #define pi acos(-1.0) struct Complex { double x,y; Complex(double a = 0,double b = 0) : x(a),y(b) {}; } ; Complex operator + (Complex a,Complex b) { return Complex(a.x + b.x,a.y + b.y);} Complex operator - (Complex a,Complex b) { return Complex(a.x - b.x,a.y - b.y);} Complex operator * (Complex a,Complex b) { return Complex(a.x * b.x - a.y * b.y,a.x * b.y + a.y * b.x);} const int maxn = 1000007; int n; Complex A[maxn],B[maxn],C[maxn]; void fft(Complex *a,int n,int type) { for(int i = 0,j = 0;i < n;++ i) { if(i < j) std::swap(a[i],a[j]); for(int k = n >> 1;(j ^= k) < k;k >>= 1); } for(int m = 2;m <= n;m <<= 1) { Complex w1 = Complex (cos(2 * pi / m),type * sin(2 * pi / m)); for(int i = 0;i < n;i += m) { Complex w = Complex(1,0); for(int k = 0;k < (m >> 1);++ k) { Complex t = w * a[i + k + (m >> 1)],u = a[i + k]; a[i + k] = u + t; a[i + k + (m >> 1)] = u - t; w = w * w1; } } } } Complex ans[maxn]; int main() { n = read(); int lim = 0; for(int tmp,i = 1;i <= n;++ i) { tmp = read(); A[tmp] = Complex(1,0); B[tmp * 2] = Complex(1,0); C[tmp * 3] = Complex(1,0); lim = std::max(lim,tmp * 3); } for(n = 1;n <= lim;n <<= 1); fft(A,n,1); fft(B,n,1); fft(C,n,1); for(int i = 0;i < n;++ i) ans[i] = A[i] + (A[i] * A[i] - B[i]) * Complex(1.0 / 2.0,0) + (A[i] * A[i] * A[i] - A[i] * B[i] * Complex(3.0,0) + Complex(2.0,0) * C[i]) * Complex(1.0 / 6.0,0); fft(ans,n,-1); for(int i = 0;i < n;++ i) { int T = ans[i].x / n + 0.5; if(T) printf("%d %d\n",i,T); } return 0; }
/* 苟活者在淡红的血色中,会依稀看到微茫的希望 */ #include<bits/stdc++.h> using namespace std; inline int read() { int x = 0,f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = - 1; c = getchar(); } while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); return x * f; } const int maxn = 1000007; const int P = 998244353,G = 3,Gi = 332748118; #define LL long long LL pre[maxn],now[maxn]; int n,m,limit = 1,k,prek,K,L,r[maxn]; inline LL fastpow(LL a, LL k) { LL base = 1; while(k) { if(k & 1) base = (base * a ) % P; a = (a * a) % P; k >>= 1; } return (base % P + P) % P; } inline void NTT(LL *A, int type) { for(int i = 0; i < limit; i++) if(i < r[i]) swap(A[i], A[r[i]]); for(int mid = 1; mid < limit; mid <<= 1) { LL Wn = fastpow( type == 1 ? G : Gi , (P - 1) / (mid << 1)); for(int j = 0; j < limit; j += (mid << 1)) { LL w = 1; for(int k = 0; k < mid; k++, w = (w * Wn) % P) { int x = A[j + k], y = w * A[j + k + mid] % P; A[j + k] = (x + y) % P, A[j + k + mid] = (x - y + P) % P; } } } } LL inv[maxn]; void work(int k,int prek) { limit = 1; L = 0; for(int c = 1,i = 1;i <= k;++ i) now[i] = c = 1ll * c * (k - i + 1) % P * inv[i] % P; while(limit <= k + prek) limit <<= 1,L ++; for(int i = 0;i < limit;++ i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1)); NTT(now,1);NTT(pre,1); for(int i = 0;i < limit;++ i) now[i] = (now[i] * pre[i]) % P; NTT(now,-1); LL inv = fastpow(limit, P - 2); for(int i = 0;i <= k + prek;++ i) now[i] = (now[i] * inv) % P; } int t[maxn]; int main() { n = read(); m = read(),K = read(); prek = read() ; for(int i = 1;i <= prek;++ i) pre[i] = 1; inv[1] = 1; for(int i = 2;i <= m;++ i) t[i - 1] = read(); random_shuffle(t + 1,t + m); for(int i = 2; i <= n; ++ i) inv[i]=1ll*(P-P/i)* inv[P % i] % P; for(int k = 0,i = 1;i < m;++ i) { k = t[i]; work(k,prek); for(int i = 0;i <= k + prek;++ i) pre[i] = now[i],now[i] = r[i] = 0; prek = k + prek; } printf("%d\n",pre[K]); return 0; }