目錄html
退役選手表示在近一兩年不會更新板子,可能大學會撿起來這個博客吧ios
離Noip也不遠了,最後\(30\)天,天天早上都會敲一敲板子.c++
隨機放出.(你們也能看一看 qwq.git
#include<cstdio> #define R register using namespace std; int n,m,f[10008]; int find(int x){return f[x]==x?x:f[x]=find(f[x]);} int main() { scanf("%d%d",&n,&m); for(R int i=1;i<=n;i++)f[i]=i; for(R int i=1,opt,a,b;i<=m;i++) { scanf("%d%d%d",&opt,&a,&b); if(opt==1) { R int fa=find(a),fb=find(b); f[fa]=fb; } else { R int fa=find(a),fb=find(b); puts(fa==fb?"Y":"N"); } } }
最長單調上升序列。算法
其餘類型的能夠改變一下符號。數組
#include<cstdio> #include<algorithm> #include<iostream> #define R register using namespace std; inline void in(R int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int stk[100008],top,n; int main() { in(n); for(R int i=1,x;i<=n;i++) { in(x); if(stk[top]<x)stk[++top]=x; else { R int l=1,r=top; while(l<=r) { R int mid=(l+r)>>1; if(stk[mid]>x)r=mid-1; else l=mid+1; } stk[l]=x; } } printf("%d\n",top); }
最長公共子序列。網絡
若是不等,狀態轉移與前面存在的三種狀態取\(max\).函數
能夠滾動數組。優化
固然也能夠樹狀數組優化。ui
這個優化必需要求:兩個串均爲全排列的某一種
不過的確懶得寫了.
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define R register using namespace std; const int gz=1e4+5; char a[gz],b[gz]; int la,lb,f[2][gz]; int main() { scanf("%s",a+1);scanf("%s",b+1); la=strlen(a+1),lb=strlen(b+1); for(R int i=1;i<=la;i++) { R int op=i&1; for(R int j=1;j<=lb;j++) { if(a[i]==b[j]) f[op][j]=f[op^1][j-1]+1; else f[op][j]=max(max(f[op^1][j],f[op][j-1]),f[op^1][j-1]); } } printf("%d\n",f[la&1][lb]); }
給出一個有理數\(c=\frac{a}{b}\),求\(c\ \bmod 19260817\)的值。
把快讀稍做模改便可.
#include<bits/stdc++.h> #define R register #define mod 19260817 using namespace std; long long a,b,ans; inline void in(long long &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10%mod+(s-'0')%mod;s=getchar();} x*=f; } inline long long ksm(long long x,long long p) { long long res=1; for(;p;p>>=1,x=x*x%mod) if(p&1)res=res*x%mod; return res; } int main() { in(a),in(b); if(b==0){printf("Angry!");return 0;} ans=a*ksm(b,mod-2); printf("%lld",(ans%mod+mod)%mod); }
注意這裏要判斷\(1^0 mod \ 1=0\)的狀況.
#include<cstdio> #define int long long #define R register using namespace std; inline int ksm(int x,int y,int p) { if(y==0)return 1; int res=1; for(;y;y>>=1,x=x*x%p) if(y&1)res=res*x%p; return res%p; } int x,y,p; signed main() { scanf("%lld%lld%lld",&x,&y,&p); printf("%lld^%lld mod %lld=%lld",x,y,p,ksm(x,y,p)%p); }
判斷奇異局勢.
若是每一堆石子異或起來的值不爲\(0\),那麼先手必勝,
若是爲\(0\),那麼先手必敗.
#include<cstdio> #include<algorithm> #include<iostream> #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int T,n; int main() { in(T); for(R int ans;T;T--) { in(n);ans=0; for(R int i=1,x;i<=n;in(x),ans^=x,i++); if(ans)puts("Yes"); else puts("No"); } }
可貴第一次寫重載,注意矩乘具備左結合右結合律的,\(ksm\)中別寫反.
#include<cstdio> #include<cctype> #include<cstring> #define int long long #define R register #define mod 1000000007 using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m; struct cod { int res[105][105]; cod(){memset(res,0,sizeof res);} inline void nw() {for(R int i=1;i<=n;i++)res[i][i]=1;} cod friend operator *(const cod&a,const cod&b) { cod tmp; for(R int k=1;k<=n;k++) for(R int i=1;i<=n;i++) for(R int j=1;j<=n;j++) (tmp.res[i][j]+=a.res[i][k]*b.res[k][j])%=mod; return tmp; } }ans,x; inline void ksm(int y) { ans.nw(); for(;y;y>>=1,x=x*x) if(y&1)ans=ans*x; } signed main() { in(n),in(m); for(R int i=1;i<=n;i++) for(R int j=1;j<=n;j++) in(x.res[i][j]); ksm(m); for(R int i=1;i<=n;i++,puts("")) for(R int j=1;j<=n;j++) printf("%lld ",ans.res[i][j]); }
開$long long \(!!,必定要開\)long long $!!!
PS:查詢最小值的答案即爲數組中最小的非零數。
#include<cstdio> #include<algorithm> #include<iostream> #define int long long #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int p[64],ans,n; inline void insert(R int x) { for(R int i=63;~i;i--) { if(x&(1LL<<i)) { if(p[i]) x^=p[i]; else { p[i]=x; break; } } } } signed main() { in(n); for(R int i=1,x;i<=n;i++) in(x),insert(x); for(R int i=63;~i;i--) if((ans^p[i])>ans) ans^=p[i]; printf("%lld",ans); }
先將數組中的全部數變成包含這個最高位且能夠經過\(Xor\)獲得的最小值。
具體實現方法:
每一位向後掃,若是能變小就變小。
求解的時候就只要將\(k\)轉化爲二進制後,將其二進制所對應位置的數異或起來便可。
部分代碼
inline int query(R int k) { R int tmp[64],res=0,cnt=0; for(R int i=0;i<=63;i++) { for(R int j=i-1;j>=0;j--) if(p[i]&(1LL<<j))p[i]^=p[j]; if(p[i])tmp[++cnt]=p[i]; } for(R int i=1;i<=cnt;i++) if(k&(1LL<<i))res^=tmp[i]; return res; }
實在懶得寫了,就直接放一下好了,注意\(p\)必須是一個較小的質數.
#include<cstdio> #include<cctype> #define int long long #define RI register int using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int T,fac[100008]; inline int ksm(int x,int y,int p) { int res=1; for(;y;y>>=1,x=x*x%p) if(y&1) res=x*res%p; return res; } inline int C(int n,int m,int p) { if(m>n)return 0; return ((ksm(fac[n-m],p-2,p)%p*ksm(fac[m],p-2,p)%p*fac[n])%p+p)%p; } int Lucas(int n,int m,int p) { if(m==0)return 1; return (Lucas(n/p,m/p,p)%p*C(n%p,m%p,p)%p+p)%p; } signed main() { in(T); fac[0]=fac[1]=1; for(RI n,m,p;T;T--) { in(n),in(m),in(p); for(RI i=2;i<=p;i++)fac[i]=fac[i-1]%p*i%p; printf("%lld\n",(Lucas(n+m,m,p)+p)%p); } }
順便寫了篩歐拉函數\(\phi\)
應該沒鍋 qwq
#include<cstdio> #define R register using namespace std; int n,m,prime[100000008],tot,phi[100000008]; bool vis[100000008]; inline void pri() { vis[1]=true; for(R int i=2;i<=n;i++) { if(!vis[i])prime[++tot]=i,phi[i]=i-1; for(R int j=1;j<=tot and i*prime[j]<=n;j++) { vis[i*prime[j]]=true; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } int main() { scanf("%d%d",&n,&m); pri(); for(R int x;m;m--) { scanf("%d",&x); puts(vis[x]==0?"Yes":"No"); } }
#include<cstdio> #include<algorithm> #define N 5000 #define R register using namespace std; struct cod{ int u,v,w; bool operator <(const cod&a)const { return w<a.w; } }edge[N*N+10]; int n,m,f[N],tot,cnt,ans; int find(int x){return f[x]==x?x:f[x]=find(f[x]);} int main() { scanf("%d%d",&n,&m); for(R int i=1;i<=n;i++)f[i]=i; for(R int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); sort(edge+1,edge+m+1); for(R int i=1;i<=m;i++) { int u=edge[i].u,v=edge[i].v,w=edge[i].w; int fu=find(u),fv=find(v); if(fu==fv)continue; ans+=w;cnt++;f[fu]=fv; if(cnt==n-1)break; } if(cnt==n-1)printf("%d",ans); else printf("orz"); }
待補ing
k在大多數狀況下接近2
#include<cstdio> #include<queue> #define N 500008 #define R register using namespace std; int n,m,s,dis[N],head[N],tot; bool vis[N]; struct cod{int u,v,w;}edge[N]; inline void add(int x,int y,int z) { edge[++tot].u=head[x]; edge[tot].v=y; edge[tot].w=z; head[x]=tot; } inline void spfa() { for(R int i=1;i<=n;i++)dis[i]=2147483647; queue<int>q; q.push(s);vis[s]=true;dis[s]=0; while(!q.empty()) { int u=q.front();q.pop();vis[u]=false; for(R int i=head[u];i;i=edge[i].u) { if(dis[edge[i].v]>dis[u]+edge[i].w) { dis[edge[i].v]=dis[u]+edge[i].w; if(!vis[edge[i].v]) { vis[edge[i].v]=true; q.push(edge[i].v); } } } } } int main() { scanf("%d%d%d",&n,&m,&s); for(R int i=1,x,y,z;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); } spfa(); for(R int i=1;i<=n;i++)printf("%d ",dis[i]); }
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #include<algorithm> #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } #define N 100086 #define clear(a) memset(a,0,sizeof a) int n,m,T; struct code{int u,v,w;}edge[N]; bool vis[N]; int head[N],tot,dis[N],cnt[N]; inline void add(int x,int y,int z) { edge[++tot].u=head[x]; edge[tot].v=y; edge[tot].w=z; head[x]=tot; } inline bool spfa(int now) { for(R int i=1;i<=n;i++) vis[i]=false,dis[i]=2147483647,cnt[i]=false; queue<int>q;q.push(now); vis[now]=true;dis[now]=0; while(!q.empty()) { int u=q.front();q.pop();vis[u]=false; if(cnt[u]>=n)return true; for(R int i=head[u];i;i=edge[i].u) { if(dis[edge[i].v]>dis[u]+edge[i].w) { dis[edge[i].v]=dis[u]+edge[i].w; if(!vis[edge[i].v]) { q.push(edge[i].v); vis[edge[i].v]=true; cnt[edge[i].v]++; if(cnt[edge[i].v]>=n)return true; } } } } return false; } int main() { in(T); while(T--) { in(n),in(m); tot=0;clear(head); for(R int i=1,u,v,w;i<=m;i++) { in(u),in(v),in(w); if(w<0)add(u,v,w); else add(u,v,w),add(v,u,w); } puts(spfa(1)?"YE5":"N0"); } }
貪心策略.不能跑最長路
#include<cstdio> #include<queue> #define N 500008 #define R register using namespace std; int n,m,s,dis[N],head[N],tot; bool vis[N]; struct cod{int u,v,w;}edge[N]; inline void add(int x,int y,int z) { edge[++tot].u=head[x]; edge[tot].v=y; edge[tot].w=z; head[x]=tot; } struct hop{ int u,d; bool operator<(const hop&a) const { return d>a.d; } }; inline void dijkstra() { for(R int i=1;i<=n;i++)dis[i]=2147483647; priority_queue<hop>q; q.push((hop){s,0});dis[s]=0; while(!q.empty()) { int u=q.top().u;q.pop(); if(vis[u])continue; vis[u]=true; for(R int i=head[u];i;i=edge[i].u) { if(dis[edge[i].v]>dis[u]+edge[i].w and !vis[edge[i].v]) { dis[edge[i].v]=dis[u]+edge[i].w; q.push((hop){edge[i].v,dis[edge[i].v]}); } } } } int main() { scanf("%d%d%d",&n,&m,&s); for(R int i=1,x,y,z;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); } dijkstra(); for(R int i=1;i<=n;i++)printf("%d ",dis[i]); }
超級短的樹狀數組 qwq
#include<cstdio> #include<cctype> #define lowbit(x) x&-x #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,tr[500008]; inline void add(int pos,int del){for(;pos<=n;pos+=lowbit(pos))tr[pos]+=del;} inline int query(int pos){int res=0;for(;pos;pos-=lowbit(pos))res+=tr[pos];return res;} int main() { in(n),in(m); for(R int i=1,x;i<=n;i++)in(x),add(i,x); for(R int opt,l,r;m;m--) { in(opt),in(l),in(r); if(opt==1)add(l,r); else printf("%d\n",query(r)-query(l-1)); } }
仍是比較短 emmm
這裏用到了差分思想,不會的能夠看看個人這篇博客
#include<cstdio> #include<cctype> #define lowbit(x) x&-x #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,tr[500008],last; inline void add(int pos,int del){for(;pos<=n;pos+=lowbit(pos))tr[pos]+=del;} inline int query(int pos){int res=0;for(;pos;pos-=lowbit(pos))res+=tr[pos];return res;} int main() { in(n),in(m);in(last);add(1,last); for(R int i=2,x;i<=n;i++) { in(x); add(i,x-last); last=x; } for(R int opt,l,r,x;m;m--) { in(opt); if(opt==1)in(l),in(r),in(x),add(l,x),add(r+1,-x); else in(x),printf("%d\n",query(x)); } }
其餘相似單點修改,大同小異,這裏給出區間修改,區間查詢好了.
#include<cstdio> #include<cctype> #define ls o<<1 #define rs o<<1|1 #define int long long #define N 100009 #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,tr[N<<2],tg[N<<2]; inline void up(int o) { tr[o]=tr[ls]+tr[rs]; } inline void down(int o,int l,int r) { if(tg[o]) { tg[ls]+=tg[o];tg[rs]+=tg[o]; int mid=(l+r)>>1; tr[ls]+=(mid-l+1)*tg[o]; tr[rs]+=(r-mid)*tg[o]; tg[o]=0; } } void build(int o,int l,int r) { if(l==r) { in(tr[o]); return; } int mid=(l+r)>>1; build(ls,l,mid);build(rs,mid+1,r); up(o); } void change(int o,int l,int r,int x,int y,int z) { if(x<=l and y>=r) { tr[o]+=(r-l+1)*z; tg[o]+=z; return; } down(o,l,r); int mid=(l+r)>>1; if(x<=mid)change(ls,l,mid,x,y,z); if(y>mid)change(rs,mid+1,r,x,y,z); up(o); } int query(int o,int l,int r,int x,int y) { if(x<=l and y>=r)return tr[o]; down(o,l,r); int mid=(l+r)>>1,res=0; if(x<=mid)res+=query(ls,l,mid,x,y); if(y>mid)res+=query(rs,mid+1,r,x,y); return res; } signed main() { in(n),in(m);build(1,1,n); for(R int opt,x,y,z;m;m--) { in(opt); if(opt==1){in(x),in(y),in(z),change(1,1,n,x,y,z);} else{in(x),in(y);printf("%lld\n",query(1,1,n,x,y));} } }
重點在於去重操做和更新操做。
#include<cstdio> #include<algorithm> #define ls o<<1 #define rs o<<1|1 #define R register using namespace std; struct code { double l,r,h; int f; bool operator < (const code&a)const { return h<a.h; } }edge[2008]; struct cod { int l,r,s; double len; }tr[8888]; double x[2333]; void build(int o,int l,int r) { tr[o].l=l,tr[o].r=r; tr[o].s=0;tr[o].len=0; if(l==r)return; int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); } inline void up(int o) { if(tr[o].s) tr[o].len=x[tr[o].r+1]-x[tr[o].l]; else if(tr[o].l==tr[o].r) tr[o].len=0; else tr[o].len=tr[ls].len+tr[rs].len; } void change(int o,int l,int r,int del) { if(tr[o].l==l && tr[o].r==r) { tr[o].s+=del; up(o); return; } int mid=(tr[o].l+tr[o].r)>>1; if(r<=mid)change(ls,l,r,del); else if(l>mid) change(rs,l,r,del); else change(ls,l,mid,del),change(rs,mid+1,r,del); up(o); } int main() { int n,cas=0; for(;;) { scanf("%d",&n); if(n==0)break; int tot=0; for(R int i=1;i<=n;i++) { R double x1,x2,y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); edge[++tot].l=x1;edge[tot].r=x2;edge[tot].h=y1; edge[tot].f=1;x[tot]=x1; edge[++tot].l=x1;edge[tot].r=x2;edge[tot].h=y2; edge[tot].f=-1;x[tot]=x2; } sort(x+1,x+tot+1); sort(edge+1,edge+tot+1); int new_n=1; for(R int i=2;i<=tot;i++) if(x[new_n]!=x[i])x[++new_n]=x[i]; build(1,1,new_n); double ans=0; for(R int i=1;i<=tot;i++) { int l=lower_bound(x+1,x+new_n+1,edge[i].l)-x; int r=lower_bound(x+1,x+new_n+1,edge[i].r)-x-1; change(1,l,r,edge[i].f); ans+=(edge[i+1].h-edge[i].h)*tr[1].len; } printf("Test case #%d\n",++cas); printf("Total explored area: %.2f\n\n",ans); } }
#include<cstdio> #include<iostream> #include<algorithm> #define N 200008 #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,a[N],b[N]; int cnt,sum[N*35],lson[N*35],rson[N*35],root[N*35]; void build(int lastroot,int &nowroot,int l,int r,int pos) { nowroot=++cnt; sum[nowroot]=sum[lastroot]+1; lson[nowroot]=lson[lastroot]; rson[nowroot]=rson[lastroot]; if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)build(lson[lastroot],lson[nowroot],l,mid,pos); else build(rson[lastroot],rson[nowroot],mid+1,r,pos); } int query(int lastroot,int nowroot,int l,int r,int pos) { if(l==r)return l; int tmp=sum[lson[nowroot]]-sum[lson[lastroot]]; int mid=(l+r)>>1; if(pos<=tmp)return query(lson[lastroot],lson[nowroot],l,mid,pos); else return query(rson[lastroot],rson[nowroot],mid+1,r,pos-tmp); } int main() { in(n),in(m); for(R int i=1;i<=n;i++)in(a[i]),b[i]=a[i]; sort(b+1,b+n+1); int new_n=1; for(R int i=2;i<=n;i++) if(b[i]!=b[new_n])b[++new_n]=b[i]; for(R int i=1;i<=n;i++) build(root[i-1],root[i],1,new_n,lower_bound(b+1,b+new_n+1,a[i])-b); for(R int i=1,l,r,k;i<=m;i++) { in(l),in(r),in(k); printf("%d\n",b[query(root[l-1],root[r],1,new_n,k)]); } }
這類題再不寫快讀,我自廢雙手好吧.
PS:不要用\(endl\)換行!
#include<iostream> #include<cmath> #include<cstdio> #include<cctype> #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int mx[100008][23],n,m; int main() { in(n),in(m); for(R int i=1;i<=n;i++)in(mx[i][0]); for(R int j=1;j<=21;j++) for(R int i=1;(i+(1<<j)-1)<=n;i++) mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]); for(R int l,r,k;m;m--) { in(l),in(r); k=log2(r-l+1); printf("%d\n",max(mx[l][k],mx[r-(1<<k)+1][k])); } }
這個東西你們不該該都是臨時手推嘛,爲何好多人都要背 emmm
假設咱們當前枚舉到了\(i\),這裏\(p\)爲模數
顯然\(p\)能夠寫成這樣
\[ p=k \times i+r\ \ \ (0\leq r<p) \]
則有
\[ k \times i+r \equiv 0 \ (mod \ p) \]
兩邊同時乘以\(r^{-1}\)和\(i^{-1}\)
\[ k \times r^{-1}+i^{-1} \equiv 0 \ (mod\ p) \]
移項。
\[ i^{-1} \equiv \ -k \times r^{-1} \ \ (mod \ p) \\ \]
而咱們的\(k\)又等價於\(\lfloor \frac{p}{i} \rfloor\) ,\(r\)等價於\(p%i\)
所以原式爲
\[ i^{-1}\equiv -1\times \lfloor \frac{p}{i} \rfloor \times[p%i ]^{-1} \ (mod\ p) \]
由於可能出負數,記得每次\(+p\)再\(%p\)便可
#include<cstdio> #include<cctype> #define int long long #define R register using namespace std; int n,p,inv[3000008]; signed main() { scanf("%lld%lld",&n,&p);inv[1]=1; for(R int i=2;i<=n;i++) inv[i]=(-1*(p/i)*inv[p%i]+p)%p; for(R int i=1;i<=n;i++) printf("%lld\n",(inv[i]+p)%p); }
主要用到了費馬小定理,這裏就手推一下好了.
這是歐拉定理.
\[ a^{\phi(p)} \equiv 1 \ (mod \ p) \]
而後當\(p\)爲質數的時候,\(\phi(p)=p-1\)
此時
\[ a^{p-1} \equiv {1}\ ( mod\ p) \]
稍做變形
\[ a^{p-2} \times a \equiv 1 \ (mod \ p) \]
此時\(a^{p-2}\)與\(a^{-1}\)等價,直接求便可。
倍增算法,直接跳便可.
#include<cstdio> #include<cctype> #include<iostream> #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,s,depth[500008]; int head[500008],tot,f[500008][21]; struct cod{int u,v;}edge[1000008]; inline void add(int x,int y) { edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot; } void dfs(int u,int fa) { depth[u]=depth[fa]+1;f[u][0]=fa; for(R int i=1;(1<<i)<=depth[u];i++) f[u][i]=f[f[u][i-1]][i-1]; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs(edge[i].v,u); } } inline int lca(int x,int y) { if(depth[x]>depth[y])swap(x,y); for(R int i=17;i>=0;i--) if(depth[x]+(1<<i)<=depth[y]) y=f[y][i]; if(x==y)return x; for(R int i=17;i>=0;i--) { if(f[x][i]==f[y][i])continue; x=f[x][i],y=f[y][i]; } return f[x][0]; } int main() { in(n),in(m),in(s); for(R int i=1,x,y;i<n;i++) { in(x),in(y); add(x,y),add(y,x); } dfs(s,0); for(R int i=1,x,y;i<=m;i++) { in(x),in(y); printf("%d\n",lca(x,y)); } }
這裏放一下板子好了 emm.新學的 qwq.
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #define int long long #define R register #define ls o<<1 #define rs o<<1|1 #define clear(a,b) memset(a,b,sizeof a) #define N 100050 using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,root,p,depth[N],size[N],f[N],top[N],dfn[N],fdfn[N]; int son[N],a[N],idx; int head[N],tot,tr[N<<2],tg[N<<2]; struct cod{int u,v;}edge[N<<1]; inline void add(int x,int y) { edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot; } inline void down(int o,int l,int r) { if(tg[o]) { int mid=(l+r)>>1; (tg[ls]+=tg[o])%=p;(tg[rs]+=tg[o])%=p; (tr[ls]+=(mid-l+1)*tg[o])%=p; (tr[rs]+=(r-mid)*tg[o])%=p; tg[o]=0; } return; } void build(int o,int l,int r) { if(l==r) { tr[o]=a[fdfn[l]]%p; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); (tr[o]=tr[ls]+tr[rs])%=p; } void change(int o,int l,int r,int x,int y,int z) { if(x<=l and y>=r) { (tr[o]+=(r-l+1)*z)%=p; (tg[o]+=z)%=p; return; } down(o,l,r); int mid=(l+r)>>1; if(x<=mid)change(ls,l,mid,x,y,z); if(y>mid)change(rs,mid+1,r,x,y,z); (tr[o]=tr[ls]+tr[rs])%=p; return; } int query(int o,int l,int r,int x,int y) { if(x<=l and y>=r) return tr[o]; down(o,l,r); int mid=(l+r)>>1,res=0; if(x<=mid)res+=query(ls,l,mid,x,y); if(y>mid) res+=query(rs,mid+1,r,x,y); return res; } void dfs1(int u,int fa) { depth[u]=depth[fa]+1;f[u]=fa;size[u]=1; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs1(edge[i].v,u); size[u]+=size[edge[i].v]; if(son[u]==-1 or size[son[u]]<size[edge[i].v]) son[u]=edge[i].v; } } void dfs2(int u,int t) { dfn[u]=++idx;fdfn[idx]=u;top[u]=t; if(son[u]==-1)return; dfs2(son[u],t); for(R int i=head[u];i;i=edge[i].u) { if(dfn[edge[i].v])continue; dfs2(edge[i].v,edge[i].v); } } inline int tchange(int x,int y,int z) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(depth[fx]>depth[fy]) { change(1,1,idx,dfn[fx],dfn[x],z); x=f[fx]; } else { change(1,1,idx,dfn[fy],dfn[y],z); y=f[fy]; } fx=top[x],fy=top[y]; } if(dfn[x]>dfn[y])swap(x,y); change(1,1,idx,dfn[x],dfn[y],z); } inline int tquery(int x,int y) { int fx=top[x],fy=top[y],ans=0; while(fx!=fy) { if(depth[fx]>depth[fy]) { (ans+=query(1,1,idx,dfn[fx],dfn[x]))%=p; x=f[fx]; } else { (ans+=query(1,1,idx,dfn[fy],dfn[y]))%=p; y=f[fy]; } fx=top[x],fy=top[y]; } if(dfn[x]>dfn[y])swap(x,y); (ans+=query(1,1,idx,dfn[x],dfn[y]))%=p; return ans; } signed main() { in(n),in(m),in(root),in(p); for(R int i=1;i<=n;i++)in(a[i]); clear(son,-1); for(R int i=1,x,y;i<n;i++) { in(x),in(y); add(x,y),add(y,x); } dfs1(root,-1);dfs2(root,root); build(1,1,idx); for(R int i=1,opt,l,r,z;i<=m;i++) { in(opt); switch(opt) { case 1:in(l),in(r),in(z),tchange(l,r,z);break; case 2:in(l),in(r);printf("%lld\n",(tquery(l,r)+p)%p);break; case 3:in(l),in(z);change(1,1,idx,dfn[l],dfn[l]+size[l]-1,z);break; case 4:in(l);printf("%lld\n",(query(1,1,idx,dfn[l],dfn[l]+size[l]-1)+p)%p);break; } } }
記得每次\(memset\).其餘沒有須要特別注意的。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int n,m,e,match[200008]; int head[200008],tot,ans; struct cod{int u,v;}edge[200008*4]; inline void add(int x,int y) { edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot; } bool vis[200008]; bool find(int x) { for(R int i=head[x];i;i=edge[i].u) { if(!vis[edge[i].v]) { vis[edge[i].v]=1; if(!match[edge[i].v] or find(match[edge[i].v])) { match[edge[i].v]=x; return true; } } } return false; } int main() { in(n),in(m),in(e); for(R int i=1,x,y;i<=e;i++) { in(x),in(y); if(y>m)continue; add(x,y); } for(R int i=1;i<=n;i++) { memset(vis,0,sizeof vis); if(find(i))ans++; } printf("%d",ans); }
考慮到\(Noip\)不考,因此沒再打一次,貼代碼.
網絡流也忘得差很少了
// luogu-judger-enable-o2 #include<bits/stdc++.h> #define IL inline #define RI register int #define N 1500000+10 IL void read(int &x){ int f=1;x=0;char s=getchar(); while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();} while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();} x*=f; } struct cod{int u,v,w;}edge[N]; int head[N],tot,s,t,depth[N],cur[N],n,m,e; IL void add(int x,int y,int z){edge[++tot].u=head[x];edge[tot].v=y;edge[tot].w=z;head[x]=tot;} IL bool bfs() { memset(depth,0,sizeof depth); std::queue<int>q; for(RI i=0;i<=n + m + 2;i++)cur[i]=head[i]; q.push(s);depth[s]=1; while(!q.empty()) { int u=q.front();q.pop(); for(RI i=head[u];i!=-1;i=edge[i].u) { if(!depth[edge[i].v]&&edge[i].w>0) { depth[edge[i].v]=depth[u]+1; q.push(edge[i].v); } } } if(!depth[t])return false;return true; } IL int dfs(int u,int dist) { if(u==t || !dist)return dist; int di=0,f; for(RI i=cur[u];i!=-1;i=edge[i].u) { cur[u]=i; if(depth[edge[i].v]==depth[u]+1 &&( f=dfs(edge[i].v,std::min(edge[i].w,dist)))) { di+=f;dist-=f; edge[i].w-=f;edge[i^1].w+=f; if(!dist)break; } } return di; } IL int dinic() { int ans=0; while(bfs()) ans+=dfs(s,2147483647); return ans; } int main() { memset(head,-1,sizeof head);tot=-1; read(n),read(m),read(e); s=0,t=n+m+1; for(RI i=1,u,v,w;i<=e;i++){ read(u),read(v); if(v<=m) { v+=n; add(u,v,1),add(v,u,0); } } for(RI i=1;i<=n;i++)add(s,i,1),add(i,s,0); for(RI i=1;i<=m;i++)add(i+n,t,1),add(t,n+i,0); printf("%d",dinic()); }
這裏用的是天然溢出哈希.才意識到跑這麼快
#include<cstdio> #include<cctype> #include<algorithm> #include<cstring> #define R register #define base 131 using namespace std; int n,ans=1; unsigned long long a[10008]; inline unsigned long long has(char *s) { int len=strlen(s); unsigned long long res=1; for(R int i=0;i<len;i++) res=res*base+(unsigned long long)s[i]; return res; } char s[1500]; int main() { scanf("%d",&n); for(R int i=1;i<=n;i++) scanf("%s",s),a[i]=has(s); sort(a+1,a+n+1); for(R int i=2;i<=n;i++) if(a[i]!=a[i-1])ans++; printf("%d",ans); }
注意存儲出現位置要寫成\(i-lb+1\)
#include<cstdio> #include<cstring> #define R register using namespace std; char s1[1008611],s2[1008611]; int la,lb,nex[1008611],k,loc[1008611],cnt; int main() { scanf("%s%s",s1+1,s2+1); la=strlen(s1+1),lb=strlen(s2+1); nex[1]=0; for(R int i=2;i<=lb;i++) { while(k and s2[k+1]!=s2[i])k=nex[k]; if(s2[i]==s2[k+1])k++; nex[i]=k; } k=0; for(R int i=1;i<=la;i++) { while(k and s2[k+1]!=s1[i])k=nex[k]; if(s1[i]==s2[k+1])k++; if(k==lb) loc[++cnt]=i-lb+1; } for(R int i=1;i<=cnt;i++) printf("%d\n",loc[i]); for(R int i=1;i<=lb;i++) printf("%d ",nex[i]); }
求\(S\)中最長迴文串的長度.(非插入字符版
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #define R register using namespace std; char ch[11000001]; char s[22000001]; int len,RL[22000001],MaxRight,center,ans; int main() { scanf("%s",ch); len=strlen(ch); for(R int i=0;i<len;i++)s[2*i+1]=ch[i]; len=2*len+1; for(R int i=0;i<len;i++) { if(i<=MaxRight) RL[i]=min(RL[2*center-i],MaxRight-i); else RL[i]=1; while(s[i-RL[i]]==s[i+RL[i]] and i-RL[i]>=0 and i+RL[i]<len) RL[i]++; if(i+RL[i]-1>MaxRight) MaxRight=i+RL[i]-1,center=i; ans=max(ans,RL[i]-1); } printf("%d",ans); }
出現的模式串的數量(就是求有多少短串在長串出現過)
#include<cstdio> #include<algorithm> #include<queue> #include<cstring> #include<iostream> #define N 1000003 #define R register using namespace std; char s[N],keyword[N]; struct AC { int sz,ch[N][26],cnt[N],val[N],last[N],fail[N],num; inline void init() { memset(ch[0],0,sizeof ch[0]); memset(cnt,0,sizeof cnt[0]); sz=1; } inline void insert(char *s) { int u=0; for(R int i=0;s[i];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]++; } inline void fai() { fail[0]=0; queue<int>q; for(R int i=0;i<26;i++) { int u=ch[0][i]; if(u) { fail[u]=0; q.push(u); } } while(!q.empty()) { int u=q.front();q.pop(); for(R int i=0;i<26;i++) { int v=ch[u][i]; if(!v) { ch[u][i]=ch[fail[u]][i]; continue; } q.push(v); fail[v]=ch[fail[u]][i]; last[v]=val[fail[v]] ? fail[v]:last[fail[v]]; } } } inline int count(char *s) { int u=0,res=0; for(R int i=0;s[i];i++) { int v=s[i]-'a'; u=ch[u][v]; if(val[u])res+=val[u],val[u]=0; int tmp=u; while(last[tmp]) { tmp=last[tmp]; if(val[tmp])res+=val[tmp],val[tmp]=0; } } return res; } }ACs; int main() { int n;scanf("%d",&n);ACs.init(); for(R int i=1;i<=n;i++) { cin>>keyword; ACs.insert(keyword); } ACs.fai();cin>>s; printf("%d\n",ACs.count(s)); }
輸出單個模式串最多出現的次數,以及輸出這個出現次數最多的模式串
#include<cstdio> #include<queue> #include<cstring> #include<iostream> #include<algorithm> #define R register using namespace std; const int maxn=1000003; char keyword[153][71]; char s[1000006]; struct AC { int ch[maxn][26],val[maxn],cnt[maxn],last[maxn],fail[maxn]; int sz; inline void init() { memset(ch[0],0,sizeof ch[0]); memset(cnt,0,sizeof cnt); sz=1; } inline void insert(R char *s,R int num) { R int u=0; for(R int i=0;s[i];i++) { R 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; } inline void fai() { memset(fail,0,sizeof fail); queue<int>q;fail[0]=0; for(R int i=0;i<26;i++) { R int u=ch[0][i]; if(u) { fail[u]=0; q.push(u); } } while(!q.empty()) { R int u=q.front();q.pop(); for(R int i=0;i<26;i++) { R int v=ch[u][i]; if(!v) { ch[u][i]=ch[fail[u]][i]; continue; } q.push(v); fail[v]=ch[fail[u]][i]; last[v]=val[fail[v]] ? fail[v]:last[fail[v]]; } } } void work(R int x) { if(x) { cnt[val[x]]++; work(last[x]); } } inline void query(R char *s) { R int u=0; for(R int i=0;s[i];i++) { R int v=s[i]-'a'; if(!ch[u][v])u=fail[u]; while(u and !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() { int T; scanf("%d",&T); while(T!=0) { R int ans=0; ac.init(); for(R int i=1;i<=T;i++) { cin>>keyword[i]; ac.insert(keyword[i],i); } ac.fai(); cin>>s; ac.query(s); for(R int i=1;i<=T;i++) if(ac.cnt[i]>ans)ans=ac.cnt[i]; printf("%d\n",ans); for(R int i=1;i<=T;i++) if(ac.cnt[i]==ans) cout<<keyword[i]<<endl; scanf("%d",&T); } }