快CSP了,放一下本身打的板子。node
/*tarjan 縮點*/ void tarajn(int x) { dfn[x]=low[x]=++cnt;zhan[++top]=x; vis[x]=1; for(int i=head[x];i;i=e[i].nt) { if(!dfn[e[i].to]) { tarjan(e[i].to); low[x]=min(low[x],low[e[i].to]); } else if(vis[e[i].to])low[x]=min(low[x],dfn[e[i].to]); } if(dfn[x]==low[x]) { int k;kuai++; do { k=zhan[top--]; c[k]=kuai; vis[k]=0; }while(x!=k); } } /*快速冪*/ LL ksm(LL a,LL b,LL mod) { LL res=1; for(;b;b>>=1,a=a*a%mod)if(b&1)res=res*a%mod; return res; } /*龜速乘*/ LL gsc(LL a,lLL b,LL mod) { LL res=0; for(;b;b>>=1,a=(a+a)%mod)if(b&1)res=(res+a)%mod; return res; } /*線性篩素數*/ for(int i=2;i<=M;++i) { if(!vis[i])prime[++tot]=i; for(int j=1;j<=tot&&prime[j]*i<=M;++j) { vis[prime[j]*i]=1; if(!(i%prime[j]))break; } } /*線性篩phi函數*/ phi[1]=1; for(int i=2;i<=M;++i) { if(!vis[i]) prime[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot&&i*p[j]<=M;++j) { vis[i*prime[j]]=1; if(!(i%prime[j])) { phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*(prime[j]-1); } } /*約數個數*/ /* he表示i的約數個數 num表示i的最小素因子的個數 */ he[1]=1;vis[1]=1;num[1]=1; for(int i=2;i<=M;++i) { if(!vis[i]) { zhi[++tot]=i; he[i]=2;num[i]=1; } for(int j=1;j<=tot&&zhi[j]*i<=M;++j) { vis[zhi[j]*i]=1; if(!(i%zhi[j])) { num[i*zhi[j]]=num[i]+1; he[zhi[j]*i]=he[i]/(num[i]+1)*(num[i*zhi[j]]+1); break; } else { num[i*zhi[j]]=1; he[zhi[j]*i]=he[zhi[j]]*he[i]; } } } /*約數和*/ /* yh表示i的約數和 xh表示i的最小素因子的等比數列的和 */ yh[1]=xh[1]=1; for(register int i=2;i<=M;++i) { if(!vis[i]) { zhi[++tot]=i; yh[i]=i+1;xh[i]=i+1; } for(register int j=1;j<=tot&&zhi[j]*i<=M;++j) { vis[i*zhi[j]]=1; if(!(i%zhi[j])) { yh[i*zhi[j]]=yh[i]/xh[i]*(xh[i]*zhi[j]+1); xh[i*zhi[j]]=xh[i]*zhi[j]+1; break; } yh[i*zhi[j]]=yh[i]*yh[zhi[j]]; xh[i*zhi[j]]=zhi[j]+1; } } for(register int i=1;i<=M;++i) xh[i]=xh[i-1]+yh[i]; /*根號求phi*/ /* a和m互質時,a^{phi(m)} == 1 mod m b>=phi(m)時,a^b == a^{(b mod phi(m)) + phi(m)} mod m */ LL solve_phi(LL x) { LL res=x; for(int i=2;i*i<=x;++i) if(!(x%i)) { res=res-res/i; while(!(x%i))x/=i; } if(x!=1)res=res-res/x; return res; } /*DIJ單源最短路*/ struct dian { int hao,dis; friend bool operator <(const dian &a,const dian &b) {return a.dis>b.dis;} }; priority_queue<dian>q; memset(dis,0x3f,sizeof dis); dis[s]=0; q.push(dian{s,0}); while(!q.empty()) { x=q.top().hao;q.pop(); if(vis[x])continue; vis[x]=1; for(int i=head[x];i;i=e[i].nt) if(dis[e[i].to]>dis[x]+e[i].dis) { dis[e[i].to]=dis[x]+e[i].dis; q.push(dian{e[i].to,dis[e[i].to]}); } } /*SPFA*/ memset(dis,0x3f,sizeof dis); dis[s]=0; q.push(s);vis[s]=1; while(!q.empty()) { x=q.front;q.pop();vis[x]=0; for(int i=head[x];i;i=e[i].nt) { if(dis[e[i].to]>dis[x]+e[i].dis) { dis[e[i].to]=dis[x]+e[i].dis; if(!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=1; } } } } /*快讀*/ inline int read() { int res=0;char ch=getchar();bool XX=false; for(;!isdigit(ch);ch=getchar())(ch=='-')&&(XX=true); for(; isdigit(ch);ch=getchar())res=(res<<3)+(res<<1)+(ch^48); return XX?-res:res; } /*快輸*/ /*注意不能輸出負數和0!*/ void Write(LL x) { if(!x)return; Write(x/10); putchar((x-x/10*10)+'0'); } /*倍增求LCA*/ void yych(int x,int f) { dep[x]=dep[f]+1;fa[x][0]=f; for(int i=1;(1<<i)<=dep[x];++i) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].nt) if(e[i].to!=f)yych(e[i].to,x); } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=21;i>=0;--i) if(dep[x]-(1<<i)>=dep[y])x=fa[x][i]; if(x==y)return x; for(int i=21;i>=0;--i) { if(fa[x][i]==fa[y][i])continue; x=fa[x][i];y=fa[y][i]; } return fa[x][0]; } /*樹鏈剖分*/ void dfs1(int x) { siz[x]=1; for(int i=head[x];i;i=e[i].nt) { if(e[i].to==fa[x])continue; dep[e[i].to]=dep[x]+1; fa[e[i].to]=x; dfs1(e[i].to); siz[x]+=siz[e[i].to]; if(siz[e[i].to]>siz[son[x]])son[x]=e[i].to; } } void dfs2(int x,int t) { dfn[x]=++cnt; a[cnt]=val[x]; top[x]=t; if(son[x])dfs2(son[x],t); else return; for(int i=head[x];i;i=e[i].nt) { if(e[i].to==fa[x]||e[i].to==son[x])continue; dfs2(e[i].to,e[i].to); } } /*快速排序*/ void my_sort(int l,int r) { int ix=l,jx=r,mid=num[(l+r)>>1]; do { while(num[ix]<mid)ix++; while(num[jx]>mid)jx--; if(ix<=jx)swap(num[ix++],num[jx--]); }while(ix<=jx); if(l<jx)my_sort(l,jx); if(ix<r)my_sort(ix,r); } /*快速排序找第k大數*/ int qsort(int l,int r,int k) { if(l==r)return a[l]; int now1=l,now2=r,mid=a[(l+r)>>1]; do { while(a[now1]<mid) now1++; while(a[now2]>mid) now2--; if(now1<=now2) swap(a[now1++],a[now2--]); }while(now1<=now2); if(l<now2&&k<=(now2-l+1)) return qsort(l,now2,k); else if(now1<r&&k>(now1-l)) return qsort(now1,r,k-(now1-l)); else return a[l+k-1]; } /*擴展歐幾里得*/ void EXGCD(int a,int b,int &x,int &y) { if(!b) { x=1;y=0; return; } EXGCD(b,a%b,x,y); int t=x;x=y;y=t-(a/b)*y; } /*中國剩餘定理*/ /*a*m*t之和*/ cin>>n; for(int i=1;i<=n;++i)scanf("%lld%lld",&p[i],&a[i]); for(int i=1;i<=n;++i)M*=p[i]; for(int i=1;i<=n;++i) { int l,k,j; m[i]=M/p[i]; int lin=exgcd(m[i],p[i],l,j); (ans+=(a[i]*m[i]*l))%=M; ans=(ans+M)%M; } /*盧卡斯定理*/ /*L(n,m)==L(n/p,m/p)*C(n%p,m%p) (mod p)*/ LL lucas(LL n,LL m) { if(!m)return 1; return lucas(n/mod,m/mod)*C(n%mod,m%mod)%mod; } /*二分*/ l=0;r=***; while(l<=r) { int mid=(l+r)>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } cout<<ans; /*lowbit*/ int lowbit(int x){return x&(-x);} /*樹狀數組查詢*/ int ask(int pos) { int res=0; for(;pos;pos-=lowbit(pos))res+=tr[pos]; return res; } /*樹狀數組修改*/ void add(int pos,int val) { for(;pos<=n;pos+=lowbit(pos))tr[pos]+=val; } /*KMP*/ int k=0;nt[1]=0; for(int i=2;i<=lenb;++i) { while(k&&b[k+1]!=b[i])k=nt[k]; if(b[k+1]==b[i])++k; nt[i]=k; } k=0; for(int i=1;i<=lena;++i) { while(k&&b[k+1]!=a[i])k=nt[k]; if(b[k+1]==a[i])++k; if(k==lenb)w[++ans]=i-lenb+1; } /*數論分塊*/ for(int l=1,r;l<=k;l=r+1) { r=k/(k/l); } /*線性求逆元*/ inv[1]=1; for(int i=2;i<=n;++i)inv[i]=(p-(p/i))*inv[p%i]%p; /* 定理1:存在歐拉路的條件:圖是連通的,有且只有2個奇點. 定理2:存在歐拉回路的條件:圖是連通的,有0個奇點. */ /*Kruskal最小生成樹*/ struct bian { int fr,to,dis; friend bool operator <(const bian &a,const bian &b){return a.dis<b.dis;} }e[100010]; int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);} void he(int x,int y){fa[find(x)]=fa[find(y)];} cin>>n>>m; for(int i=1;i<=n;++i)fa[i]=i; for(int i=1;i<=m;++i)scanf("%d%d%d",&e[i].fr,&e[i].to,&e[i].dis); sort(e+1,e+1+m); for(int i=1;i<=m;++i) { int x=find(e[i].fr),y=find(e[i].to); if(x==y)continue; he(x,y); ++k; if(k==n-1)break; } /*二分圖匹配*/ bool dfs(int x) { for(int i=1;i<=m;++i) if(f[x][i]&&(!vis[i])) { vis[i]=1; if(!g[i]||dfs(g[i])){g[i]=x;return 1;} } return 0; } cin>>n>>m>>e; for(int i=1;i<=e;++i) { scanf("%d%d",&x,&y); f[x][y]=1; } for(int i=1;i<=n;++i) { memset(vis,0,sizeof(vis)); if(dfs(i))++ans; } /*最長不降低子序列*/ d[1]=1;len=1; for(int i=2;i<=n;++i) { if(a[i]>=d[len])d[++len]=a[i]; else *upper_bound(d+1,d+1+len,a[i])=a[i]; } /*最長公共子序列*/ for(int i=1;i<=n;++i)scanf("%d",&a[i]); for(int i=1;i<=n;++i)scanf("%d",&b[i]); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(a[i]==b[j])fp[i][j]=max(dp[i][j],dp[i-1][j-1]+1); else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); /*01揹包*/ cin>>V>>n; for(int i=1;i<=n;++i)scanf("%d%d",&w[i],&k[i]); for(int i=1;i<=n;++i) for(int j=V;j>=w[i];--j) f[j]=max(f[j],f[j-w[i]]+k[i]); cout<<f[V]; /*徹底揹包*/ for(int j=w[i];j<=V;j++) /*分組揹包*/ for(int i=1;i<=100;i++) if(t[i].size()) { p=t[i].size(); for(int j=m;j>=0;j--) for(int k=0;k<p;k++) if(j>=t[i][k].weight) dp[j]=max(dp[j],dp[j-t[i][k].weight]+t[i][k].value); } /*動態開點線段樹 & 線段樹合併*/ void change(int &k,int l,int r,int pos,int val) { if(!k)k=++cnt; if(l==r) { maxx[k]+=val ;wi[k]=l; return; } if(pos<=mid)change(lson[k],l,mid,pos,val); else change(rson[k],mid+1,r,pos,val); maxx[k]=max(maxx[lson[k]],maxx[rson[k]]); if(maxx[lson[k]]>=maxx[rson[k]])wi[k]=wi[lson[k]]; else wi[k]=wi[rson[k]]; } int he(int p,int q,int l,int r) { if((!p)||(!q))return p+q; if(l==r) { maxx[p]+=maxx[q]; return p; } lson[p]=he(lson[p],lson[q],l,mid); rson[p]=he(rson[p],rson[q],mid+1,r); maxx[p]=max(maxx[lson[p]],maxx[rson[p]]); if(maxx[lson[p]]>=maxx[rson[p]])wi[p]=wi[lson[p]]; else wi[p]=wi[rson[p]]; return p; } /*ST表*/ int ask(int l, int r) { int g = log2(r - l + 1); return max(a[l][g], a[r - (1 << g) + 1][g]); } for (int i = 1; i <= n; ++i)a[i][0] = read(); for (int j = 1; j <= 24; ++j) for (int i = 1; i + (1 << j) <= n + 1; ++i) a[i][j] = max(a[i][j - 1], a[i + (1 << (j - 1))][j - 1]); /*ODT*/ #define IT set<node>::iterator struct node { int l,r; mutable int val; node(int L,int R=-1,int V=0):l(L),r(R),val(V){} friend bool operator <(const node &a,const node &b) {return a.l<b.l;} } set<node>s; IT split(int pos) { IT it=s.lower_bound(node(pos)); if(it!=s.end()&&it->l==pos)return it; --it; int L=it->l,R=it->r; long long V=it->val; s.erase(it); s.insert(node{L,pos-1,V}); return s.insert(node{pos,R,V}).first; } void tuiping(int l,int r,int v) { IT it2=split(r+1),it1=split(l); s.erase(it1,it2); s.insert(node{l,r,v}); } void add(int l,int r,int v) { IT it2=split(r+1),it1=split(l); for(;it1!=it2;++it1)it1->val+=v; } long long ask(int l,int r,int x,int mod) { IT it2=split(r+1),it1=split(l); long long res=0; for(;it1!=it2;++it1) res=(res+(long long)(it1->r-it1->l+1)*ksm(it1->val,(long long) (x),(long long) (mod)))%mod; return res; } /*三分*/ while(r-l>0.000001) { double m1=l+(r-l)/3; double m2=r-(r-l)/3; if(check(m1)>check(m2)) r=m2; else l=m1; } /*普通Trie樹*/ void Insert(int val) { int t,a=0; for(int i=30;i>=1;--i) { t=(val&(1<<(i-1)))>>(i-1); if(!tr[a][t])tr[a][t]=++cnt; a=tr[a][t]; } } int ask(int val) { int t,a=0,res=0; for(int i=30;i>=1;--i) { t=(val&(1<<(i-1)))>>(i-1); if(tr[a][!t]) { res+=(1<<(i-1)); a=tr[a][!t]; } else a=tr[a][t]; } return res; } /*manacher 馬拉車*/ scanf("%s", b + 1); lenb = strlen(b + 1); for (int i = 1; i <= lenb; ++i)a[i << 1] = b[i]; lena = lenb * 2 + 1; for (int i = 1; i <= lena; i = i + 2)a[i] = '*'; for (int i = 1; i <= lena; ++i) { bj = 1; if (r < i) { r = i; hao = i; bj = 1; } else bj = min(r - i + 1, p[2 * hao - i]); while (i + bj <= lena && i - bj >= 1 && a[i + bj] == a[i - bj])bj++; p[i] = bj; if (i + bj - 1 > r) { r = i + bj - 1; hao = i; } ans = max(ans, p[i] - 1); }