CSP 前模板
快CSP了,放一下自己打的板子。
/*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);
}