Templates
Game theory
Nim
#include<bits/stdc++.h>
using namespace std;
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,x,res=0;
scanf("%d",&n);
while(n--){
scanf("%d",&x);
res^=x;
}
puts(res==0?"No":"Yes");
}
return 0;
}
SG function
Graph theory
SPFA
void spfa(int start){
for(int i=1;i<=n;i++)dis[i]=INF,vis[i]=0;
dis[start]=0;
q[qhead=qtail=1]=start;
while(qhead<=qtail){
int u=q[qhead++];
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(dis[u]+e[i].w<dis[v]){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
vis[v]=1;
q[++qtail]=v;
}
}
}
}
}
SPFA check negative cycles
void spfa(){
for(int i=1;i<=n;i++)cnt[i]=vis[i]=0,dis[i]=INF;
dis[1]=0;
queue<int> q;
q.push(1);
while(!q.empty()){
int u=q.top();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to,w=e[i].w;
D w=e[i].a*dis[u]+e[i].b;
if(dis[u]+w<dis[v]&&cnt[v]<=n){
dis[v]=w;
if(++cnt[v]>n)dis[v]=-INF;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
}
Dijkstra
void dijkstra(int st){
for(int i=1;i<=n;i++){
dis[i]=INF;
vis[i]=0;
}
dis[st]=0;
priority_queue<P,vector<P>,greater<P> > q;
q.push(P(0,st));
while(!q.empty()){
int u=q.top().second,v;
q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];i;i=e[i].next){
v=e[i].to;
if(dis[u]+e[i].w<dis[v]&&!vis[v]){
dis[v]=dis[u]+e[i].w;
q.push(P(dis[v],v));
}
}
}
}
Floyd
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
Floyd求路径最值限制问题
例:过路费
有一天你来到了一个奇怪的国家,它有 \(N\) 个城市,城市之间有若干条双向道路连接,每条道路都有一定的费用,经过城市也要一定的费用。从一个城市到达另一个城市的总花费为路径上费用最大的城市费用(包括起点和终点)加上路径上所有的道路的费用。给出 \(Q\) 次询问,分别回答每次询问中两城市间的最少花费。保证城市之间可以互达。
#include<bits/stdc++.h>
using namespace std;
const int maxn=303,INF=0x3f3f3f3f;
int n,m,Q,p[maxn],a[maxn],g[maxn][maxn],dp[maxn][maxn];
bool cmp(int x,int y){return a[x]<a[y];}
void floyd(int k){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",a+i);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)dp[i][j]=g[i][j]=INF;
g[i][i]=0;
p[i]=i;
}
sort(p+1,p+n+1,cmp);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
g[u][v]=g[v][u]=min(g[u][v],w);
}
for(int l=1,r=1;l<=n;l=r){
for(;r<=n&&a[p[l]]==a[p[r]];r++){
floyd(p[r]);
}
for(int _i=1;_i<r;_i++){
int i=p[_i];
for(int _j=1;_j<r;_j++){
int j=p[_j];
dp[i][j]=min(dp[i][j],g[i][j]+a[p[l]]);
}
}
}
scanf("%d",&Q);
while(Q--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",dp[x][y]);
}
return 0;
}
SCC
void tarjan(int u){
dfn[u]=low[u]=++cntdfn;
stk[++top]=u;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!incyc[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
numcyc[++cntcyc]=0;
int x;
do{
x=stk[top];
top--;
numcyc[cntcyc]++;
incyc[x]=cntcyc;
}while(x!=u);
}
}
void getcyc(){
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
}
topological-sort
void topsort(){
queue<int> q;
for(int i=1;i<=n;i++){
if(indeg[i]==0){
q.push(i);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(--indeg[v]==0){
q.push(v);
}
}
}
}
bipartite-graph max-match (Hungary algorithm)
bool dfs(int u){
for(int i=0;i<int(g[u].size());i++){
int v=g[u][i];
if(vis[v])continue;
vis[v]=1;
if(!c[v]||dfs(c[v])){
d[u]=v;
c[v]=u;
return 1;
}
}
return 0;
}
int match(){
int ret=0;
for(int i=1;i<=n1;i++){
for(int j=1;j<=n2;j++)vis[j]=0;
if(dfs(i))ret++;
}
return ret;
}
int main(){
scanf("%d%d%d",&n1,&n2,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
printf("%d\n",match());
return 0;
}
bipartite-graph max-match in minimum lexicographic order (Hungary algorithm)
bool dfs(int u){
for(int i=0;i<int(g[u].size());i++){
int v=g[u][i];
if(vis[v])continue;
vis[v]=1;
if(!c[v]||dfs(c[v])){
d[u]=v;
c[v]=u;
return 1;
}
}
return 0;
}
int match(){
int ret=0;
for(int i=n1;i>=1;i--){
for(int j=1;j<=n2;j++)vis[j]=0;
if(dfs(i))ret++;
}
return ret;
}
int main(){
scanf("%d%d%d",&n1,&n2,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
for(int i=1;i<=n1;i++)sort(g[i].begin(),g[i].end());
printf("%d\n",match());
return 0;
}
bipartite-graph perfect-match in maximum weight (KM-algorithm)
bool dfs(int u){
visd[u]=1;
for(int v=1;v<=n;v++){
int tmp=ld[u]+lc[v]-g[u][v];
if(!visc[v]&&!tmp){
visc[v]=1;
if(!c[v]||dfs(c[v])){
c[v]=u;
return 1;
}
}
else if(tmp<slack[v]){
slack[v]=tmp;
}
}
return 0;
}
int km(){
for(int i=1;i<=n;i++){
c[i]=lc[i]=ld[i]=0;
for(int j=1;j<=n;j++){
ld[i]=max(ld[i],g[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)slack[j]=INF;
while(1){
for(int j=1;j<=n;j++)visc[j]=visd[j]=0;
if(dfs(i))break;
int res=INF;
for(int v=1;v<=n;v++){
if(!visc[v]){
res=min(res,slack[v]);
}
}
for(int u=1;u<=n;u++){
if(visd[u]){
ld[u]-=res;
}
}
for(int v=1;v<=n;v++){
if(visc[v]){
lc[v]+=res;
}
else{
slack[v]-=res;
}
}
}
}
int ans=0;
for(int i=1;i<=n;i++)ans+=ld[i]+lc[i];
return ans;
}
network-flow (Dinic)
bool bfs(){
for(int i=1;i<=n;i++)dep[i]=0,head1[i]=head[i];
dep[s]=1;
int *qhead=q,*qtail=q;
*qtail++=s;
while(qhead!=qtail){
int u=*qhead++;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(e[i].w&&dep[v]==0){
dep[v]=dep[u]+1;
*qtail++=v;
}
}
}
return dep[t]!=0;
}
int dfs(int u,int low){
if(low==0||u==t)return low;
int flow=0;
for(int &i=head1[u];~i;i=e[i].next){
int v=e[i].to;
if(e[i].w&&dep[v]==dep[u]+1){
int tmp=dfs(v,min(low,e[i].w));
if(tmp==0)dep[v]=0;
else{
flow+=tmp;
low-=tmp;
e[i].w-=tmp;
e[i^1].w+=tmp;
if(low==0)break;
}
}
}
return flow;
}
int dinic(){
int ans=0;
while(bfs())ans+=dfs(s,INF);
return ans;
}
int main(){
int m;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=n;i++)head[i]=-1;
cnte=-1;
while(m--){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
printf("%d",dinic());
return 0;
}
network-flow (SPFA+EK)
bool spfa(){
for(int i=1;i<=n;i++)flow[i]=dis[i]=INF,vis[i]=0;
pre[t]=-1;
dis[s]=0;
queue<int> q;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(e[i].w>0&&dis[u]+e[i].cost<dis[v]){
dis[v]=dis[u]+e[i].cost;
pre[v]=u;
edg[v]=i;
flow[v]=min(flow[u],e[i].w);
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
return pre[t]!=-1;
}
void micmxf(){
while(spfa()){
int x=t;
while(x!=s){
e[edg[x]].w-=flow[t];
e[edg[x]^1].w+=flow[t];
x=pre[x];
}
maxflow+=flow[t];
mincost+=flow[t]*dis[t];
}
}
int main(){
int m;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=0;i<=n;i++)head[i]=-1;
cnte=-1;
for(int i=1;i<=m;i++){
int u,v,w,cost;
scanf("%d%d%d%d",&u,&v,&w,&cost);
add(u,v,w,cost);
add(v,u,0,-cost);
}
micmxf();
printf("%d %d\n",maxflow,mincost);
return 0;
}
MST (Prim)
void prim(){
for(int i=1;i<=n;i++)dis[i]=INT_MAX;
priority_queue<pii,vector<pii>,greater<pii> > q;
q.push(make_pair(0,1));
while(!q.empty()){
int d=q.top().first,u=q.top().second;
q.pop();
if(vis[u])continue;
ans+=d;
vis[u]=1;
cnt++;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(dis[v]>e[i].w&&!vis[v]){
dis[v]=e[i].w;
q.push(make_pair(dis[v],v));
}
}
}
}
MST (Kruskal)
void kruskal(){
sort(e+1,e+m+1);
ufset s(n);
for(int i=1;i<=m;i++){
int u=e[i].from,v=e[i].to;
if(s.same(u,v))continue;
ans+=e[i].w;
s.Union(u,v);
if(++tot==n-1)break;
}
}
Strictly second-best MST
#include<bits/stdc++.h>
#define maxn 100003
#define maxm 300003
#define INF 100000000000000000ll
using namespace std;
typedef long long D;
D n,m,lg[maxn];
namespace G{
struct edge{
D from,to,w;
bool vis;
bool operator <(const edge& x)const{return w<x.w;}
}e[maxm];
D cnte;
void add(D u,D v,D w){e[++cnte]=(edge){u,v,w,0};}
}
namespace MST{
struct edge{
D to,next,w;
}e[maxn<<1];
D head[maxn],cnte,dep[maxn],fa[maxn][23],mx[maxn][23][2];
void add(D u,D v,D w){e[++cnte]=(edge){v,head[u],w},head[u]=cnte;}
void calc(D &X0,D &X1,D Y0,D Y1,D Z0,D Z1){
X0=max(Y0,Z0);
if(Y0!=Z0)X1=max(min(Y0,Z0),max(Y1,Z1));
else X1=max(Y1,Z1);
}
void init(D u,D last){
fa[u][0]=last;
dep[u]=dep[last]+1;
for(D i=1;(1<<i)<=dep[u];i++){
D up=fa[u][i-1];
fa[u][i]=fa[up][i-1];
calc(mx[u][i][0],mx[u][i][1],mx[u][i-1][0],mx[u][i-1][1],mx[up][i-1][0],mx[up][i-1][1]);
}
for(D i=head[u];i;i=e[i].next){
D v=e[i].to;
if(v==last)continue;
mx[v][0][0]=e[i].w;
init(v,u);
}
}
D lca(D x,D y){
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y]){
x=fa[x][lg[dep[x]-dep[y]]];
}
if(x==y)return x;
for(D i=lg[dep[x]];i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
D query(D x,D y,D w){
D l=lca(x,y);
D ans0=0,ans1=0;
while(x!=l){
calc(ans0,ans1,ans0,ans1,mx[x][lg[dep[x]-dep[l]]][0],mx[x][lg[dep[x]-dep[l]]][1]);
x=fa[x][lg[dep[x]-dep[l]]];
}
while(y!=l){
calc(ans0,ans1,ans0,ans1,mx[y][lg[dep[y]-dep[l]]][0],mx[y][lg[dep[y]-dep[l]]][1]);
y=fa[y][lg[dep[y]-dep[l]]];
}
if(w!=ans0)return w-ans0;
if(ans1)return w-ans1;
return INF;
}
}
D f[maxn];
D find(D x){
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
D kruskal(){
D cnt=0,ret=0;
sort(G::e+1,G::e+m+1);
for(D i=1;i<=n;i++)f[i]=i;
for(D i=1;i<=m;i++){
D u=G::e[i].from,v=G::e[i].to,fu=find(u),fv=find(v);
if(fu!=fv){
f[fu]=fv;
ret+=G::e[i].w;
G::e[i].vis=1;
MST::add(u,v,G::e[i].w);
MST::add(v,u,G::e[i].w);
cnt++;
if(cnt>=n)break;
}
}
return ret;
}
signed main(){
scanf("%lld%lld",&n,&m);
for(D i=1;i<=m;i++){
D u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
G::add(u,v,w);
}
D ans1=kruskal(),ans2=INF;
for(D i=2;i<maxn;i++)lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i);
MST::init(1,0);
for(D i=1;i<=m;i++){
if(!G::e[i].vis){
D u=G::e[i].from,v=G::e[i].to;
ans2=min(ans2,MST::query(u,v,G::e[i].w));
}
}
printf("%lld\n",ans1+ans2);
return 0;
}
LCA (Heavy-light decomposition)
void initdep(int u,int last){
sz[u]=1;
fa[u]=last;
int mx=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u])continue;
dep[v]=dep[u]+1;
initdep(v,u);
sz[u]+=sz[v];
if(sz[v]>mx)mx=sz[v],son[u]=v;
}
}
void initdfn(int u,int tp){
dfn[u]=++cntdfn;
num[cntdfn]=u;
top[u]=tp;
if(son[u]){
initdfn(son[u],tp);
}
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]||v==son[u])continue;
initdfn(v,v);
}
rig[u]=cntdfn;
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
return y;
}
LCA (ST RMQ)
void init(int u,int last){
st[++cntdfn][0]=u;
dfn[u]=cntdfn;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
dep[v]=dep[u]+1;
init(v,u);
st[++cntdfn][0]=u;
}
}
int MIN(int x,int y){return dep[x]<dep[y]?x:y;}
void initst(){
for(int len=1;(1<<len)<=cntdfn;len++){
for(int i=1;i+(1<<len)-1<=cntdfn;i++){
st[i][len]=MIN(st[i][len-1],st[i+(1<<(len-1))][len-1]);
}
}
}
int lca(int x,int y){
if(dfn[x]>dfn[y])swap(x,y);
int tmp=lg[dfn[y]-dfn[x]+1];
return MIN(st[dfn[x]][tmp],st[dfn[y]-(1<<tmp)+1][tmp]);
}
LCA (doubling)
void init(int u){
for(int i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa[u][0])continue;
fa[v][0]=u;
dep[v]=dep[u]+1;
init(v);
}
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]];
if(x==y)return x;
for(int i=lg[dep[x]];i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
Virtual tree
#include<bits/stdc++.h>
using namespace std;
const int maxn=250003,maxm=500003,INF=0x3f3f3f3f;
struct edge{int to,next,w;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v,int w){e[++cnte].to=v,e[cnte].w=w,e[cnte].next=head[u],head[u]=cnte;}
int n,lg[maxn],fa[maxn][23],cntdfn,dfn[maxn],rig[maxn],dep[maxn],p[maxn<<2],
mi[maxn],stk[maxn],top;
long long dp[maxn];
bool vis[maxn];
void init(int u,int last){
dfn[u]=++cntdfn;
fa[u][0]=last;
for(int i=1;(1<<i)<=dep[u];i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
dep[v]=dep[u]+1;
mi[v]=min(mi[u],e[i].w);
init(v,u);
}
rig[u]=++cntdfn;
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]];
if(x==y)return x;
for(int i=lg[dep[x]];i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
bool cmp(int x,int y){return (x>0?dfn[x]:rig[-x])<(y>0?dfn[y]:rig[-y]);}
int main(){
for(int i=2;i<maxn;i++)lg[i]=lg[i-1]+((1<<(lg[i-1]+1))==i);
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
mi[1]=INF;
init(1,0);
int Q;
scanf("%d",&Q);
while(Q--){
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d",p+i),vis[p[i]]=1,dp[p[i]]=mi[p[i]];
sort(p+1,p+m+1,cmp);
for(int i=2;i<=m;i++){
int l=lca(p[i-1],p[i]);
if(vis[l])continue;
vis[l]=1;
p[++m]=l;
}
for(int i=m;i>=1;i--)p[++m]=-p[i];
if(!vis[1]){
p[++m]=1,p[++m]=-1;
vis[1]=1;
}
sort(p+1,p+m+1,cmp);
top=0;
for(int i=1;i<m;i++){
if(p[i]>0){
stk[++top]=p[i];
}
else{
int u=stk[top--],last=stk[top];
dp[last]+=min(dp[u],(long long)mi[u]);
vis[u]=0,dp[u]=0;
}
}
printf("%lld\n",dp[1]);
vis[1]=0,dp[1]=0;
}
return 0;
}
Tree-plus-cycle (containing multiple edges)
bool init(int u){
stk[++top]=u;
instk[u]=1;
for(int i=head[u];i;i=e[i].next){
int id=(i+1)>>1;
if(vis[id])continue;
vis[id]=1;
int v=e[i].to;
if(instk[v]){
int x;
do{
x=stk[top--];
p[++tot]=x;
}while(x!=v);
return 1;
}
if(init(v))return 1;
}
top--;
return 0;
}
Divide-and-conquer on tree
例:【模板】点分治
#include<bits/stdc++.h>
using namespace std;
const int maxn=10003,INF=0x3f3f3f3f;
struct edge{int to,next,w;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v,int w){e[++cnte].to=v,e[cnte].w=w,e[cnte].next=head[u],head[u]=cnte;}
int n,m,k,dis[maxn],cntdis;
bool vis[maxn];
namespace GG{
int sz[maxn],G,szG;
int inittrsz(int u,int last){
int trsz=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last||vis[v])continue;
trsz+=inittrsz(v,u);
}
return trsz;
}
void getG1(int u,int last,int trsz){
int ret=0;
sz[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last||vis[v])continue;
getG1(v,u,trsz);
ret=max(ret,sz[v]);
sz[u]+=sz[v];
}
ret=max(ret,trsz-sz[u]);
if(ret<szG){
szG=ret;
G=u;
}
}
int getG(int u){
int trsz=inittrsz(u,0);
szG=INF;
getG1(u,0,trsz);
return G;
}
}
void work(int u,int last,int depth){
dis[++cntdis]=depth;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last||vis[v])continue;
work(v,u,depth+e[i].w);
}
}
int solve(int u,int kk){
cntdis=0;
work(u,0,0);
sort(dis+1,dis+cntdis+1);
int ans=0;
pair<int*,int*> tmp;
for(int i=1;i<=cntdis;i++){
tmp=equal_range(dis+i+1,dis+cntdis+1,kk-dis[i]);
ans+=tmp.second-tmp.first;
}
return ans;
}
bool dfs(int g){
int ans=solve(g,k);
vis[g]=1;
for(int i=head[g];i;i=e[i].next){
int v=e[i].to;
if(vis[v])continue;
ans-=solve(v,k-(e[i].w<<1));
}
if(ans)return 1;
for(int i=head[g];i;i=e[i].next){
int v=e[i].to;
if(vis[v])continue;
int gg=GG::getG(v);
if(dfs(gg))return 1;
}
return 0;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
int g=GG::getG(1);
while(m--){
scanf("%d",&k);
for(int i=1;i<=n;i++)vis[i]=0;
puts(dfs(g)?"AYE":"NAY");
}
return 0;
}
DSU on tree
#include<bits/stdc++.h>
using namespace std;
const int maxn=100003;
struct edge{int to,next;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
int n,a[maxn],sz[maxn],son[maxn],buc[maxn],mxcnt;
long long sum,ANS[maxn];
void init(int u,int last){
sz[u]=1;
int res=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
init(v,u);
sz[u]+=sz[v];
if(sz[v]>res)res=sz[v],son[u]=v;
}
}
void add(int u,int last,int heavy){
buc[a[u]]++;
if(buc[a[u]]>mxcnt)mxcnt=buc[a[u]],sum=a[u];
else if(buc[a[u]]==mxcnt)sum+=a[u];
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last||v==heavy)continue;
add(v,u,heavy);
}
}
void del(int u,int last){
buc[a[u]]--;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
del(v,u);
}
}
void dfs(int u,int last,bool keep){
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last||v==son[u])continue;
dfs(v,u,0);
}
if(son[u])dfs(son[u],u,1);
add(u,last,son[u]);
ANS[u]=sum;
if(!keep){
mxcnt=sum=0;
del(u,last);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",a+i);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
init(1,0);
dfs(1,0,0);
for(int i=1;i<=n;i++)printf("%lld ",ANS[i]);
return 0;
}
Data structures
Heavy-light-decomposition
namespace SEG{
struct node{
long long sum,z;
}t[maxn<<2];
void pushdown(int p,int l,int r){
if(l==r){t[p].z=0;return;}
if(t[p].z){
int mid=(l+r)>>1;
PlusEqual(t[p<<1].sum,L(t[p].z*(mid-l+1)));
PlusEqual(t[p<<1|1].sum,L(t[p].z*(r-mid)));
PlusEqual(t[p<<1].z,t[p].z);
PlusEqual(t[p<<1|1].z,t[p].z);
t[p].z=0;
}
}
void pushup(int p,int l,int r){
t[p].sum=L(t[p<<1].sum+t[p<<1|1].sum);
}
void build(int p,int l,int r){
t[p].z=0;
if(l==r){
t[p].sum=a[num[l]];
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p,l,r);
}
void change(int p,int l,int r,int pos,long long k){
pushdown(p,l,r);
if(l==r){
PlusEqual(t[p].sum,k);
return;
}
int mid=(l+r)>>1;
if(pos<=mid)change(p<<1,l,mid,pos,k);
else change(p<<1|1,mid+1,r,pos,k);
pushup(p,l,r);
}
void change(int p,int l,int r,int seg_l,int seg_r,long long k){
pushdown(p,l,r);
if(seg_l<=l&&r<=seg_r){
PlusEqual(t[p].sum,L(k*(r-l+1)));
t[p].z=k;
return;
}
int mid=(l+r)>>1;
if(seg_l<=mid)change(p<<1,l,mid,seg_l,seg_r,k);
if(seg_r>mid)change(p<<1|1,mid+1,r,seg_l,seg_r,k);
pushup(p,l,r);
}
long long query(int p,int l,int r,int seg_l,int seg_r){
pushdown(p,l,r);
if(seg_l<=l&&r<=seg_r){
return t[p].sum;
}
int mid=(l+r)>>1;
long long ret=0;
if(seg_l<=mid)PlusEqual(ret,query(p<<1,l,mid,seg_l,seg_r));
if(seg_r>mid)PlusEqual(ret,query(p<<1|1,mid+1,r,seg_l,seg_r));
return ret;
}
}
void initdep(int u,int last,int depth){
fa[u]=last;
dep[u]=depth;
sz[u]=1;
int mxsz=0;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa[u])continue;
initdep(v,u,depth+1);
sz[u]+=sz[v];
if(sz[v]>mxsz)mxsz=sz[v],son[u]=v;
}
}
void initdfn(int u,int tp){
dfn[u]=++cntdfn;
num[cntdfn]=u;
top[u]=tp;
if(son[u]){
initdfn(son[u],tp);
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fa[u]||v==son[u])continue;
initdfn(v,v);
}
}
rig[u]=cntdfn;
}
void change(int u,long long w){
SEG::change(1,1,n,dfn[u],w);
}
void change(int x,int y,long long w){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
SEG::change(1,1,n,dfn[top[x]],dfn[x],w);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
SEG::change(1,1,n,dfn[y],dfn[x],w);
}
void changesub(int u,long long w){
SEG::change(1,1,n,dfn[u],rig[u],w);
}
long long query(int x,int y){
long long ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
PlusEqual(ans,SEG::query(1,1,n,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
PlusEqual(ans,SEG::query(1,1,n,dfn[y],dfn[x]));
return ans;
}
long long querysub(int x){
return SEG::query(1,1,n,dfn[x],rig[x]);
}
LCT
例:QTREE
#include<stdio.h>
#define maxn 20003
void swap(int *x,int *y){int t=*x;*x=*y;*y=t;}
int max(int x,int y){return x>y?x:y;}
struct node{
int val,mx,fa,son[2],z;
}t[maxn];
int isroot(int p){return t[t[p].fa].son[0]!=p&&t[t[p].fa].son[1]!=p;}
int chk(int p){return t[t[p].fa].son[1]==p;}
void reverse(int p){if(p==0)return;swap(&t[p].son[0],&t[p].son[1]);t[p].z^=1;}
void pushup(int p){t[p].mx=max(max(t[t[p].son[0]].mx,t[t[p].son[1]].mx),t[p].val);}
void pushdown(int p){
if(t[p].z){
reverse(t[p].son[0]);
reverse(t[p].son[1]);
t[p].z=0;
}
}
void pushall(int p){if(!isroot(p))pushall(t[p].fa);pushdown(p);}
void rotate(int p){
int q=t[p].fa,r=t[q].fa,k=chk(p),s=t[p].son[!k];
t[q].son[k]=s,t[s].fa=q;
if(!isroot(q))t[r].son[chk(q)]=p;
t[p].fa=r;
t[p].son[!k]=q,t[q].fa=p;
pushup(q);
pushup(p);
}
void splay(int p){
pushall(p);
while(!isroot(p)){
int q=t[p].fa;
if(!isroot(q)){
if(chk(p)==chk(q))rotate(q);
else rotate(p);
}
rotate(p);
}
}
void new_node(int p,int fa,int k){t[p].fa=fa,t[p].mx=t[p].val=k;}
void access(int x){for(int y=0;x;y=x,x=t[x].fa)splay(x),t[x].son[1]=y,pushup(x);}
void change(int x,int k){splay(x),t[x].val=k,pushup(x);}
void makeroot(int x){access(x),splay(x),reverse(x);}
int query(int x,int y){makeroot(x),access(y),splay(y);return t[y].mx;}
struct edge{int to,next;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
int n,a[maxn],ed[maxn];
void dfs(int u,int last){
new_node(u,last,a[u]);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
dfs(v,u);
}
}
void init(){
for(int i=0;i<=(n<<1);i++)t[i].val=t[i].mx=t[i].fa=t[i].son[0]=t[i].son[1]=t[i].z=head[i]=a[i]=ed[i]=0;
cnte=0;
}
char mo[13];
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=1;i<n;i++){
int u,v,w;
scanf("%d",&u),scanf("%d",&v),scanf("%d",&w);
add(u,i+n),add(i+n,u),add(i+n,v),add(v,i+n);
ed[i]=i+n;
a[i+n]=w;
}
n=n+n-1;
dfs(1,0);
while(scanf("%s",mo),*mo!='D'){
int x,y;
scanf("%d",&x),scanf("%d",&y);
if(*mo=='Q'){
printf("%d\n",query(x,y));
}
else{
change(ed[x],y);
}
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=100003,INF=0x3f3f3f3f;
template<typename tp>
void read(tp& x){
x=0;
char c=getchar();
bool sgn=0;
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')sgn=1,c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
if(sgn)x=-x;
}
template<typename tp>
void write(tp x){
if(x<0)putchar('-'),write(-x);
else{
if(x>=10)write(x/10);
putchar(x%10+'0');
}
}
struct edge{int to,next;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
int n,fa[maxn],val[maxn],a[maxn];
struct LCT{
struct node{
int mx,fa,son[2];
};node t[maxn];
multiset<int,greater<int> > light[maxn];
bool isroot(int p){return t[t[p].fa].son[0]!=p&&t[t[p].fa].son[1]!=p;}
bool chk(int p){return t[t[p].fa].son[1]==p;}
void pushup(int p){
t[p].mx=max(max(max(t[t[p].son[0]].mx,t[t[p].son[1]].mx),a[p]),light[p].empty()?-INF:*light[p].begin());
}
void rotate(int p){
int q=t[p].fa,r=t[q].fa,k=chk(p),s=t[p].son[!k];
t[q].son[k]=s,t[s].fa=q;
if(!isroot(q))t[r].son[chk(q)]=p;
t[p].fa=r;
t[p].son[!k]=q,t[q].fa=p;
pushup(q);
pushup(p);
}
void splay(int p){
while(!isroot(p)){
int q=t[p].fa,r=t[q].fa;
if(!isroot(q)){
if(chk(p)==chk(q))rotate(q);
else rotate(p);
}
rotate(p);
}
}
int find(int p){
while(t[p].son[0])p=t[p].son[0];
splay(p);
return p;
}
void access(int x){
for(int y=0;x;y=x,x=t[x].fa){
splay(x);
light[x].insert(t[t[x].son[1]].mx);
t[x].son[1]=y;
light[x].erase(light[x].lower_bound(t[t[x].son[1]].mx));
pushup(x);
}
}
void link(int x){
if(fa[x]==0)return;
access(fa[x]),splay(fa[x]),splay(x);
t[x].fa=fa[x];
light[fa[x]].insert(t[x].mx);
pushup(fa[x]);
}
void cut(int x){
if(fa[x]==0)return;
access(x),splay(x);
t[x].son[0]=t[t[x].son[0]].fa=0;
pushup(x);
}
int query(int x){
access(x),splay(x);
int tmp=find(x);
return val[tmp]==val[x]?t[tmp].mx:t[t[tmp].son[1]].mx;
}
void init(int n){for(int i=0;i<=n;i++)t[i].mx=-INF,t[i].fa=t[i].son[0]=t[i].son[1]=0;}
}tree[2];
void dfs(int u,int last){
fa[u]=last;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==last)continue;
dfs(v,u);
}
}
int main(){
read(n);
tree[0].init(n);
tree[1].init(n);
for(int i=0;i<=n;i++)a[i]=-INF;
for(int i=1;i<n;i++){
int u,v;
read(u),read(v);
add(u,v),add(v,u);
}
for(int i=1;i<=n;i++)read(val[i]);
for(int i=1;i<=n;i++)read(a[i]),tree[0].t[i].mx=tree[1].t[i].mx=a[i];
dfs(1,0);
for(int i=1;i<=n;i++)tree[val[i]].link(i);
int Q;
read(Q);
while(Q--){
int mo,x;
read(mo),read(x);
if(mo==1){
tree[val[x]].cut(x);
val[x]^=1;
tree[val[x]].link(x);
}
else if(mo==2){
int y;
read(y);
tree[0].access(x),tree[0].splay(x),tree[1].access(x),tree[1].splay(x);
a[x]=y;
tree[0].pushup(x),tree[1].pushup(x);
}
else{
write(tree[val[x]].query(x)),putchar('\n');
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=300003;
template<typename tp>
void read(tp& x){
x=0;
char c=getchar();
bool sgn=0;
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')sgn=1,c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
if(sgn)x=-x;
}
template<typename tp>
void write(tp x){
if(x<0)putchar('-'),write(-x);
else{
if(x>=10)write(x/10);
putchar(x%10+'0');
}
}
int n,a[maxn];
struct node{
int sum,fa,son[2];
bool z;
}t[maxn];
bool isroot(int p){return t[t[p].fa].son[0]!=p&&t[t[p].fa].son[1]!=p;}
bool chk(int p){return t[t[p].fa].son[1]==p;}
void reverse(int p){if(p==0)return;swap(t[p].son[0],t[p].son[1]);t[p].z^=1;}
void pushup(int p){
t[p].sum=t[t[p].son[0]].sum^t[t[p].son[1]].sum^a[p];
}
void pushdown(int p){
if(t[p].z){
reverse(t[p].son[0]);
reverse(t[p].son[1]);
t[p].z=0;
}
}
void pushall(int p){if(!isroot(p))pushall(t[p].fa);pushdown(p);}
void rotate(int p){
int q=t[p].fa,r=t[q].fa,k=chk(p),s=t[p].son[!k];
t[q].son[k]=s,t[s].fa=q;
if(!isroot(q))t[r].son[chk(q)]=p;
t[p].fa=r;
t[p].son[!k]=q,t[q].fa=p;
pushup(q);
pushup(p);
}
void splay(int p){
pushall(p);
while(!isroot(p)){
int q=t[p].fa;
if(!isroot(q)){
if(chk(p)==chk(q))rotate(q);
else rotate(p);
}
rotate(p);
}
}
void access(int x){for(int y=0;x;y=x,x=t[x].fa)splay(x),t[x].son[1]=y,pushup(x);}
void change(int x,int k){splay(x),a[x]=k,pushup(x);}
void makeroot(int x){access(x),splay(x),reverse(x);}
int findroot(int x){
access(x),splay(x);
while(t[x].son[0])pushdown(x),x=t[x].son[0];
splay(x);
return x;
}
int query(int x,int y){makeroot(x),access(y),splay(y);return t[y].sum;}
bool link(int x,int y){
makeroot(x);
if(findroot(y)==x)return 0;
t[x].fa=y;
return 1;
}
bool cut(int x,int y){
makeroot(x);
if(findroot(y)!=x||t[y].fa!=x||t[y].son[0])return 0;
t[y].fa=t[x].son[1]=0;
pushup(x);
return 1;
}
int main(){
int Q;
read(n),read(Q);
for(int i=1;i<=n;i++)read(a[i]),t[i].sum=a[i];
while(Q--){
int mo,x,y;
read(mo),read(x),read(y);
if(mo==0){
write(query(x,y)),putchar('\n');
}
else if(mo==1){
link(x,y);
}
else if(mo==2){
cut(x,y);
}
else{
change(x,y);
}
}
return 0;
}
单调队列
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000003;
int a[maxn],n,k,q[maxn],qhead,qtail;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",a+i);
qhead=1,qtail=0;
for(int i=1;i<=n;i++){
while(qhead<=qtail&&a[i]<=a[q[qtail]])qtail--;
q[++qtail]=i;
while(qhead<=qtail&&i-q[qhead]>=k)qhead++;
if(i>=k)printf("%d ",a[q[qhead]]);
}
puts("");
qhead=1,qtail=0;
for(int i=1;i<=n;i++){
while(qhead<=qtail&&a[i]>=a[q[qtail]])qtail--;
q[++qtail]=i;
while(qhead<=qtail&&i-q[qhead]>=k)qhead++;
if(i>=k)printf("%d ",a[q[qhead]]);
}
return 0;
}
Heap
template<typename tp>
class heap{
tp h[1000002];
int cnt;
public:
heap():cnt(0){}
void push(const tp &x){
h[++cnt]=x;
int p=cnt;
while(p>=2&&h[p>>1]>h[p]){
swap(h[p>>1],h[p]);
p>>=1;
}
}
void pop(){
swap(h[1],h[cnt]);
cnt--;
int p=1;
while((p<<1)<=cnt){
p<<=1;
if(p<cnt&&h[p|1]<h[p])p|=1;
if(h[p]<h[p>>1])swap(h[p],h[p>>1]);
else break;
}
}
const tp &top(){
return h[1];
}
};
单调栈
for(int i=1;i<=n;i++){
int top=0;
for(int j=1;j<=n;j++){
if(b[i][j])a[j]=i;
int tot=1;
while(top&&a[j]>=a[stk[top]]){
D tmp=at(a[stk[top]]+1,stk[top]-cnt[top]+1,i,j-1);
if(tmp>ans){
ans=tmp;
x1=a[stk[top]]+1,y1=stk[top]-cnt[top]+1,x2=i,y2=j-1;
}
tot+=cnt[top];
top--;
}
stk[++top]=j;
cnt[top]=tot;
}
while(top){
D tmp=at(a[stk[top]]+1,stk[top]-cnt[top]+1,i,n);
if(tmp>ans){
ans=tmp;
x1=a[stk[top]]+1,y1=stk[top]-cnt[top]+1,x2=i,y2=n;
}
top--;
}
}
左偏树
int new_node(int val){
t[++cnt].val=val;
return cnt;
}
void merge(int &p,int x,int y){
if(x==0||y==0){p=x+y;return;}
if(a[t[x].val]!=a[t[y].val]?a[t[x].val]>a[t[y].val]:t[x].val>t[y].val)swap(x,y);
p=x;
merge(R(p),R(x),y);
if(dis[L(p)]<dis[R(p)])swap(L(p),R(p));
dis[p]=dis[R(p)]+1;
}
void pop(int &p){
merge(p,L(p),R(p));
}
DSU
int f[maxn];
int find(int x){return x!=f[x]?f[x]=find(f[x]):x;}
void Union(int x,int y){int fx=find(x),fy=find(y);if(fx!=fy)f[fx]=fy;}
bool same(int x,int y){return find(x)==find(y);}
ST algorithm
void init(){
for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;
for(int len=1;(1<<len)<=n;len++){
for(int i=1;i+(1<<len)-1<=n;i++){
st[i][len]=max(st[i][len-1],st[i+(1<<(len-1))][len-1]);
}
}
}
int query(int l,int r){
int tmp=lg[r-l+1];
return max(st[l][tmp],st[r-(1<<tmp)+1]fe[tmp]);
}
Fenwick tree
int t[maxn];
void add(int pos,int k){while(pos<=n)t[pos]+=k,pos+=pos&-pos;}
int query(int pos){int ret=0;while(pos)ret+=t[pos],pos-=pos&-pos;return ret;}
Segment tree
merge
void merge(int &p,int q){
if(!p||!q){p|=q;return;}
cnt++;
sz[cnt]=sz[p]+sz[q];
p=cnt;
merge(L[p],L[q]);
merge(R[p],R[q]);
}
树套树
#include<bits/stdc++.h>
#define L(p) t[p].son[0]
#define R(p) t[p].son[1]
using namespace std;
const int maxn=100005,maxv=100000000,INF=2147483647;
struct treap_node{
int val,son[2],sz;
}t[4000005];
int cnt,n,a[maxn];
struct TREAP{
int root;
TREAP():root(0){}
void O(int p){
if(p==0)return;
O(L(p));
printf("%d ",t[p].val);
O(R(p));
}
void DEBUG(){
printf("###### DEBUG root:%d ######\n",root);
O(root);
printf("\n###### ######\n");
}
void pushup(int p){t[p].sz=t[L(p)].sz+t[R(p)].sz+1;}
void split(int p,int k,int &x,int &y){
if(p==0){x=y=0;return;}
if(t[p].val<=k){
x=p;
split(R(p),k,R(p),y);
}
else{
y=p;
split(L(p),k,x,L(p));
}
pushup(p);
}
void merge(int &p,int x,int y){
if(x==0||y==0){p=x+y;return;}
if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
merge(R(x),R(x),y);
pushup(x);
p=x;
}
else{
merge(L(y),x,L(y));
pushup(y);
p=y;
}
}
int new_node(int k){
cnt++;
t[cnt].val=k;
t[cnt].sz=1;
return cnt;
}
void insert(int k){
int p,x,y;
split(root,k,x,y);
p=new_node(k);
merge(p,x,p);
merge(root,p,y);
}
void erase(int k){
int x,y,z;
split(root,k,x,y);
split(x,k-1,z,x);
merge(z,z,L(x));
merge(y,R(x),y);
merge(root,z,y);
}
int rnk(int k){
int x,y;
split(root,k-1,x,y);
int ret=t[x].sz+1;
merge(root,x,y);
return ret;
}
int kth(int p,int k){
while(1){
if(k<=t[L(p)].sz)p=L(p);
else{
k-=(t[L(p)].sz+1);
if(k<=0)return p;
p=R(p);
}
}
}
int pre(int k){
int x,y;
split(root,k-1,x,y);
if(t[x].sz==0)return -INF;
int ret=kth(x,t[x].sz);
merge(root,x,y);
return t[ret].val;
}
int nxt(int k){
int x,y;
split(root,k,x,y);
if(t[y].sz==0)return INF;
int ret=kth(y,1);
merge(root,x,y);
return t[ret].val;
}
};
struct SEG{
struct seg_node{
TREAP tr;
}t[maxn<<2];
void build(int p,int l,int r){
for(int i=l;i<=r;i++)t[p].tr.insert(a[i]);
if(l==r)return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void change(int p,int l,int r,int pos,int k){
t[p].tr.erase(a[pos]);
t[p].tr.insert(k);
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)change(p<<1,l,mid,pos,k);
else change(p<<1|1,mid+1,r,pos,k);
}
int _rnk(int p,int l,int r,int seg_l,int seg_r,int k){
if(seg_l<=l&&r<=seg_r)return t[p].tr.rnk(k)-1;
int mid=(l+r)>>1,ret=0;
if(seg_l<=mid)ret+=_rnk(p<<1,l,mid,seg_l,seg_r,k);
if(seg_r>mid)ret+=_rnk(p<<1|1,mid+1,r,seg_l,seg_r,k);
return ret;
}
int rnk(int seg_l,int seg_r,int k){
return _rnk(1,1,n,seg_l,seg_r,k)+1;
}
int kth(int seg_l,int seg_r,int k){
int l=0,r=maxv,mid,ans=-1;
while(l<=r){
mid=(l+r)>>1;
if(rnk(seg_l,seg_r,mid)<=k)ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int pre(int p,int l,int r,int seg_l,int seg_r,int k){
if(seg_l<=l&&r<=seg_r)return t[p].tr.pre(k);
int mid=(l+r)>>1,ret=-INF;
if(seg_l<=mid)ret=max(ret,pre(p<<1,l,mid,seg_l,seg_r,k));
if(seg_r>mid)ret=max(ret,pre(p<<1|1,mid+1,r,seg_l,seg_r,k));
return ret;
}
int nxt(int p,int l,int r,int seg_l,int seg_r,int k){
if(seg_l<=l&&r<=seg_r)return t[p].tr.nxt(k);
int mid=(l+r)>>1,ret=INF;
if(seg_l<=mid)ret=min(ret,nxt(p<<1,l,mid,seg_l,seg_r,k));
if(seg_r>mid)ret=min(ret,nxt(p<<1|1,mid+1,r,seg_l,seg_r,k));
return ret;
}
}seg;
int main(){
srand(19260817);
int Q,mo,x,y,z;
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;i++)scanf("%d",a+i);
seg.build(1,1,n);
while(Q--){
scanf("%d%d%d",&mo,&x,&y);
switch(mo){
case 1:scanf("%d",&z),printf("%d\n",seg.rnk(x,y,z));break;
case 2:scanf("%d",&z),printf("%d\n",seg.kth(x,y,z));break;
case 3:seg.change(1,1,n,x,y),a[x]=y;break;
case 4:scanf("%d",&z),printf("%d\n",seg.pre(1,1,n,x,y,z));break;
case 5:scanf("%d",&z),printf("%d\n",seg.nxt(1,1,n,x,y,z));break;
}
}
return 0;
}
Treap
维护权值
#include<bits/stdc++.h>
#define maxn 100003
using namespace std;
struct node{
int val,son[2],sz;
}t[maxn];
int cnt,root;
void pushup(int p){t[p].sz=t[t[p].son[0]].sz+t[t[p].son[1]].sz+1;}
void split(int p,int k,int &x,int &y){
if(p==0){x=y=0;return;}
if(t[p].val<=k){
x=p;
split(t[p].son[1],k,t[p].son[1],y);
}
else{
y=p;
split(t[p].son[0],k,x,t[p].son[0]);
}
pushup(p);
}
void merge(int &p,int x,int y){
if(x==0||y==0){p=x+y;return;}
if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
merge(t[x].son[1],t[x].son[1],y);
pushup(x);
p=x;
}
else{
merge(t[y].son[0],x,t[y].son[0]);
pushup(y);
p=y;
}
}
int new_node(int k){
cnt++;
t[cnt].val=k;
t[cnt].sz=1;
return cnt;
}
void insert(int k){
int p,x,y;
split(root,k,x,y);
p=new_node(k);
merge(p,x,p);
merge(root,p,y);
}
void erase(int k){
int x,y,z;
split(root,k,x,y);
split(x,k-1,z,x);
merge(z,z,t[x].son[0]);
merge(y,t[x].son[1],y);
merge(root,z,y);
}
int rnk(int k){
int x,y;
split(root,k-1,x,y);
int ret=t[x].sz+1;
merge(root,x,y);
return ret;
}
int kth(int p,int k){
while(1){
if(k<=t[t[p].son[0]].sz)p=t[p].son[0];
else{
k-=(t[t[p].son[0]].sz+1);
if(k<=0)return p;
p=t[p].son[1];
}
}
}
int pre(int k){
int x,y;
split(root,k-1,x,y);
int ret=kth(x,t[x].sz);
merge(root,x,y);
return ret;
}
int nxt(int k){
int x,y;
split(root,k,x,y);
int ret=kth(y,1);
merge(root,x,y);
return ret;
}
int main(){
srand(19260817);
int Q;
scanf("%d",&Q);
while(Q--){
int mo,x;
scanf("%d%d",&mo,&x);
switch(mo){
case 1:insert(x);break;
case 2:erase(x);break;
case 3:printf("%d\n",rnk(x));break;
case 4:printf("%d\n",t[kth(root,x)].val);break;
case 5:printf("%d\n",t[pre(x)].val);break;
case 6:printf("%d\n",t[nxt(x)].val);break;
}
}
return 0;
}
维护序列
#include<bits/stdc++.h>
#define L(p) t[p].son0
#define R(p) t[p].son1
using namespace std;
const int maxn=100003;
struct node{
int son0,son1,sz;
bool z;
}t[maxn];
int cnt,root;
void pushup(int p){t[p].sz=t[L(p)].sz+t[R(p)].sz+1;}
void solve(int p){if(p)swap(L(p),R(p)),t[p].z^=1;}
void pushdown(int p){
if(t[p].z){
solve(L(p)),solve(R(p));
t[p].z=0;
}
}
void output(int p){
if(p==0)return;
pushdown(p);
output(L(p));
printf("%d ",p);
output(R(p));
}
void O(int p=root){
output(p);
puts("");
}
void split(int p,int k,int &x,int &y){
if(p==0){x=y=0;return;}
pushdown(p);
if(t[L(p)].sz+1<=k){
x=p;
split(R(p),k-t[L(p)].sz-1,R(p),y);
}
else{
y=p;
split(L(p),k,x,L(p));
}
pushup(p);
}
void merge(int &p,int x,int y){
if(x==0||y==0){p=x+y;return;}
if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
pushdown(x);
merge(R(x),R(x),y);
pushup(x);
p=x;
}
else{
pushdown(y);
merge(L(y),x,L(y));
pushup(y);
p=y;
}
}
void build(int &p,int l,int r){
if(l>r)return;
p=(l+r)>>1;
build(L(p),l,p-1);
build(R(p),p+1,r);
pushup(p);
}
void reverse(int l,int r){
int x,y,z;
split(root,l-1,x,y);
split(y,r-l+1,y,z);
solve(y);
merge(y,x,y);
merge(root,y,z);
}
int main(){
srand(19260817);
int n,Q;
scanf("%d%d",&n,&Q);
build(root,1,n);
while(Q--){
int x,y;
scanf("%d%d",&x,&y);
reverse(x,y);
}
O();
return 0;
}
persistent
#include<bits/stdc++.h>
#define L(p) t[p].son[0]
#define R(p) t[p].son[1]
using namespace std;
namespace FASTIO{...}
const int maxn=200003;
struct node{
int val,son[2],sz;
long long sum;
bool z;
}t[20000003];
int cnt,root[maxn];
int new_node(int k){
cnt++;
t[cnt].val=t[cnt].sum=k;
t[cnt].sz=1;
L(cnt)=R(cnt)=0;
return cnt;
}
void pushup(int p){
t[p].sz=t[L(p)].sz+t[R(p)].sz+1;
t[p].sum=t[L(p)].sum+t[R(p)].sum+t[p].val;
}
void pushdown(int p){
if(t[p].z){
int l=0,r=0;
if(L(p))t[r=++cnt]=t[L(p)],t[r].z^=1;
if(R(p))t[l=++cnt]=t[R(p)],t[l].z^=1;
L(p)=l,R(p)=r;
t[p].z=0;
}
}
void output(int p){
if(p==0)return;
pushdown(p);
output(L(p));
printf("val:%d sum:%lld son0:%d son1:%d\n",t[p].val,t[p].sum,t[L(p)].val,t[R(p)].val);
output(R(p));
}
void O(int p){
printf("### O ###\n");
puts("############");
output(p);
puts("############");
}
void split(int p,int k,int &x,int &y){
if(p==0){x=y=0;return;}
pushdown(p);
if(t[L(p)].sz+1<=k){
x=++cnt;
t[x]=t[p];
split(R(p),k-t[L(p)].sz-1,R(x),y);
pushup(x);
}
else{
y=++cnt;
t[y]=t[p];
split(L(p),k,x,L(y));
pushup(y);
}
}
void merge(int &p,int x,int y){
if(x==0||y==0){p=x+y;return;}
if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
pushdown(x);
merge(R(x),R(x),y);
pushup(x);
p=x;
}
else{
pushdown(y);
merge(L(y),x,L(y));
pushup(y);
p=y;
}
}
void insert(int u,int v,int pos,int k){
int x,y;
split(root[v],pos,x,y);
merge(x,x,new_node(k));
merge(root[u],x,y);
}
void erase(int u,int v,int pos){
int x,y,z;
split(root[v],pos-1,x,y);
split(y,1,y,z);
merge(root[u],x,z);
}
void reverse(int u,int v,int l,int r){
int x,y,z;
split(root[v],l-1,x,y);
split(y,r-l+1,y,z);
t[y].z^=1;
merge(y,x,y);
merge(root[u],y,z);
}
long long query(int v,int l,int r){
int x,y,z;
split(root[v],l-1,x,y);
split(y,r-l+1,y,z);
long long ret=t[y].sum;
merge(y,x,y);
merge(root[v],y,z);
return ret;
}
int main(){
srand(19260817);
int Q,v,mo;
long long x,y,last=0;
read(Q);
for(int i=1;i<=Q;i++){
read(v),read(mo),read(x);
root[i]=root[v];
x^=last;
if(mo==1){
read(y);
y^=last;
insert(i,v,x,y);
}
if(mo==2){
erase(i,v,x);
}
if(mo==3){
read(y);
y^=last;
reverse(i,v,x,y);
}
if(mo==4){
read(y);
y^=last;
write(last=query(v,x,y)),pc('\n');
}
}
flush();
return 0;
}
String
KMP
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000003;
int kmp[maxn];
char s1[maxn],s2[maxn];
int main(){
scanf("%s%s",s1+1,s2+1);
int l1=strlen(s1+1),l2=strlen(s2+1),pos=0;
for(int i=2;i<=l2;i++){
while(pos&&s2[pos+1]!=s2[i])pos=kmp[pos];
if(s2[pos+1]==s2[i])pos++;
kmp[i]=pos;
}
pos=0;
for(int i=1;i<=l1;i++){
while(pos&&s1[i]!=s2[pos+1])pos=kmp[pos];
if(s1[i]==s2[pos+1])pos++;
if(pos==l2){
printf("%d\n",i-l2+1);
pos=kmp[pos];
}
}
for(int i=1;i<=l2;i++)printf("%d ",kmp[i]);
return 0;
}
Hash
#include<bits/stdc++.h>
using namespace std;
const int maxn=10003;
char s[maxn];
int n,ha[maxn];
int hash(){
static const int p1=15797,p2=1000000009;
int ret=0;
for(int i=0;s[i];i++){
ret=(1ll*ret*p1+s[i])%p2;
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s);
ha[i]=hash();
}
sort(ha+1,ha+n+1);
printf("%d",int(unique(ha+1,ha+n+1)-ha-1));
return 0;
}
Suffix array
#include<bits/stdc++.h>
#define maxn 1000003
#define mod 1000000007
#define O(a) printf(#a": ");for(int j=1;j<=n;j++)printf("%d ",a[j]);puts("")
#define DEBUG printf("%d:\n",(int)__LINE__);O(sa);O(rnk);O(tp);O(buc);O(height)
using namespace std;
char s[maxn];
int rnk[maxn],sa[maxn],tp[maxn],buc[maxn],n,m,height[maxn],a[maxn],f[maxn];
long long sum[maxn];
void bucsort(){
for(int i=1;i<=m;i++)buc[i]=0;
for(int i=1;i<=n;i++)buc[rnk[i]]++;
for(int i=1;i<=m;i++)buc[i]+=buc[i-1];
for(int i=n;i>=1;i--)sa[buc[rnk[tp[i]]]--]=tp[i];
}
void sufsort(){
m=128;
for(int i=1;i<=n;i++)rnk[i]=s[i],tp[i]=i;
bucsort();
for(int t=1,cnt=0;cnt<n;m=cnt,t<<=1){
//update tp
cnt=0;
for(int i=n-t+1;i<=n;i++)tp[++cnt]=i;
for(int i=1;i<=n;i++){
if(sa[i]>t)tp[++cnt]=sa[i]-t;
}
//update sa
bucsort();
//update rnk
for(int i=1;i<=n;i++)tp[i]=rnk[i];
rnk[sa[1]]=cnt=1;
for(int i=2;i<=n;i++){
rnk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+t]==tp[sa[i-1]+t]?cnt:++cnt);
}
}
}
void geth(){
int k=0;
for(int i=1;i<=n;i++)rnk[sa[i]]=i;
for(int i=1;i<=n;i++){
if(rnk[i]==1)continue;
if(k)k--;
int j=sa[rnk[i]-1];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
height[rnk[i]]=k;
}
}
bool cmp(int x,int y){return height[x]>height[y];}
int find(int x){return x!=f[x]?f[x]=find(f[x]):f[x];}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
sufsort(),geth();
for(int i=1;i<=n;i++)a[i]=f[i]=i,sum[i]=1;
sort(a+1,a+n+1,cmp);
long long ans=0;
for(int i=n,j=1;i>=1;i--){
for(;j<=n&&height[a[j]]==i;j++){
int x=find(sa[a[j]-1]),y=find(sa[a[j]]);
sum[x]+=sum[y];
ans=max(ans,(long long)i*sum[x]);
f[y]=x;
}
}
printf("%lld\n",ans);
return 0;
}
Manacher
#include<bits/stdc++.h>
using namespace std;
const int maxn=22000005;
char t[maxn>>1],s[maxn];
int p[maxn];
int main(){
scanf("%s",t+1);
int N=strlen(t+1),n=0,mid=0,r=0,ans=1;
s[++n]=-2,s[++n]=-1;
for(int i=1;i<=N;i++)s[++n]=t[i],s[++n]=-1;
for(int i=1;i<=n;i++){
if(i<=r)p[i]=min(p[(mid<<1)-i],r-i+1);
while(s[i+p[i]]==s[i-p[i]])p[i]++;
if(i+p[i]-1>r)r=i+p[i]-1,mid=i;
ans=max(ans,p[i]);
}
printf("%d\n",ans-1);
return 0;
}
Geometry
const double eps=1e-10,INF=1e17;
typedef double tp;
int sgn(tp x){return x<-eps?-1:x>eps;}
// const double pi=acos(-1);
struct point{
tp x,y;
point(){}
point(tp _x,tp _y):x(_x),y(_y){}
void write()const{printf("%.4lf %.4lf\n",x,y);}
bool operator<(point p)const{return sgn(x-p.x)==0?sgn(y-p.y)<0:sgn(x-p.x)<0;}
bool operator==(point p)const{return sgn(x-p.x)==0&&sgn(y-p.y)==0;}
point operator+(point p)const{return point(x+p.x,y+p.y);}
point operator-(point p)const{return point(x-p.x,y-p.y);}
point operator*(tp k)const{return point(x*k,y*k);}
double norm()const{return x*x+y*y;}
// double abs()const{return sqrt(x*x+y*y);}
};
tp dot(point u,point v){return u.x*v.x+u.y*v.y;}
tp cross(point u,point v){return u.x*v.y-v.x*u.y;}
double dist(point p1,point p2){return sqrt(double(dot(p1-p2,p1-p2)));}
point inter(point P,point v,point Q,point w){
point u=P-Q;
if(sgn(cross(v,w))==0){
if(sgn(cross(Q-P,v))==0)return point(-INF,-INF); //chong he
return point(INF,INF); //ping xing
}
tp t=cross(w,u)/cross(v,w);
return P+v*t; //OK
}
bool seg_inter(point p1,point p2,point p3,point p4){
return min(p1.x,p2.x)<=max(p3.x,p4.x)&&
min(p3.x,p4.x)<=max(p1.x,p2.x)&&
min(p1.y,p2.y)<=max(p3.y,p4.y)&&
min(p3.y,p4.y)<=max(p1.y,p2.y)&&
sgn(cross(p2-p1,p3-p1))*sgn(cross(p2-p1,p4-p1))<=0&&
sgn(cross(p4-p3,p1-p3))*sgn(cross(p4-p3,p2-p3))<=0;
}
bool line_seg_inter(point l1,point l2,point p1,point p2){
return sgn(cross(l2-l1,p1-l1))*sgn(cross(l2-l1,p2-l1))<=0;
}
int stk[maxn],cntcon;
point con[maxn];
void convex_hull(point a[],int n){
cntcon=0;
int top=2;
stk[1]=1,stk[2]=2;
for(int i=3;i<=n;i++){
while(top>1&&cross(a[i]-a[stk[top]],a[stk[top]]-a[stk[top-1]])>0)top--;
stk[++top]=i;
}
for(int i=1;i<top;i++){
con[++cntcon]=a[stk[i]];
}
top=2;
stk[1]=1,stk[2]=2;
for(int i=3;i<=n;i++){
while(top>1&&cross(a[i]-a[stk[top]],a[stk[top]]-a[stk[top-1]])<=0)top--;
stk[++top]=i;
}
for(int i=top;i>1;i--){
con[++cntcon]=a[stk[i]];
}
}
double getS(const vector<point> &p){
double ans=cross(p[0],p[p.size()-1]);
for(int i=1;i<int(p.size());i++)ans+=cross(p[i],p[i-1]);
return abs(ans)*0.5;
}
bool onright(point P,point S,point T){
return sgn(cross(T-S,P-S))<0;
}
Math
Number theory
Combinatorics
Gauss
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=103;
const double eps=1e-8;
int n;
double a[maxn][maxn];
int sgn(double x){return x<-eps?-1:x>eps;}
bool gauss(){
for(int i=1;i<=n;i++){
int p=i;
for(int j=i+1;j<=n;j++)if(abs(a[j][i])>abs(a[p][i]))p=j;
if(p!=i)for(int j=1;j<=n+1;j++)swap(a[i][j],a[p][j]);
if(sgn(a[i][i])==0){
puts("No Solution");
return 0;
}
for(int j=i+1;j<=n+1;j++)a[i][j]/=a[i][i];
a[i][i]=1;
for(int j=1;j<=n;j++){
if(i!=j){
for(int k=i+1;k<=n+1;k++)a[j][k]-=a[j][i]*a[i][k];
a[j][i]=0;
}
}
}
return 1;
}
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n+1;j++){
scanf("%lf",&a[i][j]);
}
}
if(!gauss())return 0;
for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]);
return 0;
}
Linear basis
#include<bits/stdc++.h>
using namespace std;
const int maxlog=51;
int n;
long long p[maxlog];
void insert(long long x){
for(int i=maxlog-1;i>=0;i--){
if((x>>i)&1){
if(p[i]==0){
p[i]=x;
break;
}
else x^=p[i];
}
}
}
long long query(){
long long ret=0;
for(int i=maxlog-1;i>=0;i--){
if((ret^p[i])>ret)ret^=p[i];
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
long long x;
scanf("%lld",&x);
insert(x);
}
printf("%lld",query());
return 0;
}
BSGS
unordered_map<int,int> mp;
int bsgs(int y,int z){
if(z==1)return 0;
if(y%mod==0)return -1;
mp.clear();
int m=sqrt(mod)+1,ji=z;
for(int b=0;b<=m;b++){
mp[ji]=b;
ji=mul(ji,y);
}
int tmp=qpow(y,m);
ji=1;
for(int a=1;a<=m;a++){
ji=mul(ji,tmp);
if(mp.count(ji))return a*m-mp[ji];
}
return -1;
}