后缀自动机
#include<bits/stdc++.h>
#define re register
#define ll long long
#define inc(i,j,k) for(re int i=j;i<=k;i++)
using namespace std;
const int MAXN=1000005;
struct state{
int len,link,mp[30];
}st[MAXN<<1];
struct edge{
int to,nxt;
}e[MAXN<<1];
queue<int> q;
ll ans;
char s[MAXN];
int sz,last,cnt,head[MAXN<<1],num[MAXN<<1];
void add(int a,int b){
e[++cnt].to=b;
e[cnt].nxt=head[a];
head[a]=cnt;
}
void sa_init(){
st[sz].len=0;
st[sz].link=-1;
last=sz;
}
void sa_extend(int c){
int cur=++sz;
num[sz]=1;
st[cur].len=st[last].len+1;
int p=last;
while(p!=-1&&!st[p].mp[c]){
st[p].mp[c]=cur;
p=st[p].link;
}
if(p==-1) st[cur].link=0;
else{
int q=st[p].mp[c];
if(st[q].len==st[p].len+1) st[cur].link=q;
else{
int clone=++sz;
st[clone].len=st[p].len+1;
inc(i,0,25) st[clone].mp[i]=st[q].mp[i];
st[clone].link=st[q].link;
while(p!=-1&&st[p].mp[c]==q){
st[p].mp[c]=clone;
p=st[p].link;
}
st[q].link=st[cur].link=clone;
}
}
last=cur;
}
void dfs(int u){
for(re int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
dfs(v);
num[u]+=num[v];
}
if(num[u]!=1) ans=max(ans,(ll)num[u]*st[u].len);
}
int main(){
scanf("%s",s+1);
int len=strlen(s+1);
sa_init();
inc(i,1,len) sa_extend(s[i]-'a');
inc(i,1,sz) add(st[i].link,i);
dfs(0);
printf("%lld",ans);
}
后缀数组
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
using namespace std;
const int MAXN=1000005;
char s[MAXN];
int sa[MAXN],rank[MAXN],tp[MAXN],a[MAXN],n,m,cnt[MAXN];
void sa_sort(){
inc(i,0,m) cnt[i]=0;
inc(i,1,n) cnt[rank[tp[i]]]++;
inc(i,1,m) cnt[i]+=cnt[i-1];
dec(i,n,1) sa[cnt[rank[tp[i]]]--]=tp[i];
}
void get_sa(){
inc(i,1,n) rank[i]=a[i],tp[i]=i;
m=127,sa_sort();
for(re int k=1,p=0;p<n;k<<=1,m=p){
p=0;
inc(i,n-k+1,n) tp[++p]=i;
inc(i,1,n) if(sa[i]>k) tp[++p]=sa[i]-k;
sa_sort(),swap(rank,tp),rank[sa[1]]=p=1;
inc(i,2,n) rank[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+k]==tp[sa[i-1]+k])?p:++p;
}
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
inc(i,1,n) a[i]=s[i];
get_sa();
inc(i,1,n) printf("%d ",sa[i]);
}
回文自动机
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
using namespace std;
const int N=5e5+5;
char s[N];
int ch[N][26],len[N],fa[N],num[N],tot,ans,last;
void init(){tot=1,fa[0]=fa[1]=1,len[1]=-1;}
void extend(int c,int i){
int p=last;
while(s[i-len[p]-1]!=s[i]) p=fa[p];
if(!ch[p][c]){
int k=fa[p];
while(s[i-len[k]-1]!=s[i]) k=fa[k];
fa[++tot]=ch[k][c];
ch[p][c]=tot;
len[tot]=len[p]+2,num[tot]=num[fa[tot]]+1;
}
printf("%d ",ans=num[ch[p][c]]);
last=ch[p][c];
}
int main(){
scanf("%s",s+1);
int n=strlen(s+1);init();
inc(i,1,n) s[i]=(s[i]-97+ans)%26+97,extend(s[i]-'a',i);
}
AC自动机
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
return f*x;
}
const int MAXN=200005;
queue<int> qq;
int n,ch[MAXN][26],nxt[MAXN],tot,cnt,val[MAXN],ru[MAXN],head[MAXN],num,ans[MAXN],pos[MAXN];
char s[MAXN*10];
struct edge{
int to,nxt;
}e[MAXN];
void add(int a,int b){
e[++num].to=b;
e[num].nxt=head[a];
head[a]=num;
}
void insert(char *s){
int len=strlen(s+1);
int u=0;
inc(i,1,len){
int c=s[i]-'a';
if(!ch[u][c]) ch[u][c]=++tot;
u=ch[u][c];
}
pos[++cnt]=u;
}
void build(){
queue<int> q;
inc(i,0,25) if(ch[0][i]) nxt[ch[0][i]]=0,q.push(ch[0][i]);
while(q.size()){
int u=q.front();
q.pop();
inc(i,0,25){
if(ch[u][i]) nxt[ch[u][i]]=ch[nxt[u]][i],q.push(ch[u][i]);
else ch[u][i]=ch[nxt[u]][i];
}
}
}
void find(char *s){
int len=strlen(s+1);
int u=0;
inc(i,1,len){
int c=s[i]-'a';
u=ch[u][c],val[u]++;
}
}
int main(){
n=read();
inc(i,1,n){
scanf("%s",s+1);
insert(s);
}
build();
scanf("%s",s+1);
find(s);
inc(i,1,tot) add(i,nxt[i]),ru[nxt[i]]++;
inc(i,1,tot) if(!ru[i]) qq.push(i);
while(qq.size()){
int u=qq.front();
qq.pop();
for(re int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
val[v]+=val[u];
ru[v]--;
if(!ru[v]) qq.push(v);
}
}
inc(i,1,n) printf("%d\n",val[pos[i]]);
}
Z函数
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define ll long long
using namespace std;
const int N=2e7+5;
inline int read(){
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
char s[N],t[N];
int n,m,z[N],p[N];
ll ans;
void getz(){
z[1]=m;int l=0,r=0;
inc(i,2,m){
if(i<=r) z[i]=min(z[i-l+1],r-i+1);
while(i+z[i]<=m&&t[i+z[i]]==t[z[i]+1]) z[i]++;
if(i+z[i]-1>r) l=i,r=i+z[i]-1;
}
}
void exkmp(){
int l=0,r=0;
inc(i,1,n){
if(i<=r) p[i]=min(z[i-l+1],r-i+1);
while(i+p[i]<=n&&s[i+p[i]]==t[p[i]+1]) p[i]++;
if(i+p[i]-1>r) l=i,r=i+p[i]-1;
}
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
scanf("%s",t+1);
m=strlen(t+1);
getz(),exkmp();
ans=0;
inc(i,1,m) ans^=1LL*i*(z[i]+1);
printf("%lld\n",ans);
ans=0;
inc(i,1,n) ans^=1LL*i*(p[i]+1);
printf("%lld\n",ans);
}
kmp
#include<bits/stdc++.h>
#define maxn 1000010
using namespace std;
char a[maxn],b[maxn];
int nxt[maxn];
int main(){
scanf("%s",a+1);
scanf("%s",b+1);
int j=0;
int la=strlen(a+1),lb=strlen(b+1);
for(int i=2;i<=lb;++i){
while(j && b[i]!=b[j+1]) j=nxt[j];
if(b[i]==b[j+1]) j++;
nxt[i]=j;
}
j=0;
for(int i=1;i<=la;++i){
while(j && a[i]!=b[j+1]) j=nxt[j];
if(a[i]==b[j+1]) j++;
if(j==lb){
printf("%d\n",i-lb+1);
j=nxt[j];
}
}
for(int i=1;i<=lb;++i) printf("%d ",nxt[i]);
return 0;
}
线段树套平衡树
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
using namespace std;
const int MAXN=4000005;
const int inf=2147483647;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
return f*x;
}
struct Splay{
int root[MAXN],cnt;
struct tree{
int ch[2],pre,val,size,cnt;
#define fa(x) t[x].pre
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
}t[MAXN];
bool check(int x){return rc(fa(x))==x;}
void connect(int x,int fa,int type){fa(x)=fa,t[fa].ch[type]=x;}
void pushup(int x){t[x].size=t[lc(x)].size+t[rc(x)].size+t[x].cnt;}
void rotate(int x){
int y=fa(x),z=fa(y),k=check(x),w=t[x].ch[k^1];
fa(x)=z;
if(z) connect(x,z,check(y));
connect(w,y,k);
connect(y,x,k^1);
pushup(y),pushup(x);
}
void splay(int x,int goal,int k){
while(fa(x)!=goal){
int y=fa(x);
if(fa(y)!=goal){
if(check(x)==check(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(!goal) root[k]=x;
}
void insert(int val,int k){
int tmp=root[k],p=0;
while(tmp&&t[tmp].val!=val) p=tmp,tmp=t[tmp].ch[val>t[tmp].val];
if(tmp) t[tmp].cnt++;
else{
tmp=++cnt;
fa(tmp)=p;
if(p) connect(tmp,p,val>t[p].val);
t[tmp].val=val;
t[tmp].size=t[tmp].cnt=1;
}
splay(tmp,0,k);
}
void find(int val,int k){
int tmp=root[k];
while(t[tmp].ch[val>t[tmp].val]&&val!=t[tmp].val) tmp=t[tmp].ch[val>t[tmp].val];
splay(tmp,0,k);
}
int pre(int val,int k){
find(val,k);
if(t[root[k]].val<val) return root[k];
int tmp=lc(root[k]);
while(rc(tmp)) tmp=rc(tmp);
return tmp;
}
int nxt(int val,int k){
find(val,k);
if(t[root[k]].val>val) return root[k];
int tmp=rc(root[k]);
while(lc(tmp)) tmp=lc(tmp);
return tmp;
}
void remove(int val,int k){
int first=pre(val,k),last=nxt(val,k);
splay(first,0,k),splay(last,first,k);
int tmp=lc(last);
if(t[tmp].cnt>1){
t[tmp].cnt--;
splay(tmp,0,k);
}
else lc(last)=0;
}
int rank(int x,int val){
if(!x) return 0;
if(t[x].val<val) return t[lc(x)].size+t[x].cnt+rank(rc(x),val);
if(t[x].val==val) return t[lc(x)].size;
return rank(lc(x),val);
}
}bt;
int n,m,a[MAXN];
struct tree{
#define ls o<<1
#define rs o<<1|1
void build(int o,int l,int r){
bt.insert(inf,o),bt.insert(-inf,o);
inc(i,l,r) bt.insert(a[i],o);
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
}
void change(int o,int l,int r,int pos,int val){
bt.remove(a[pos],o),bt.insert(val,o);
if(l==r){a[pos]=val;return;}
int mid=l+r>>1;
if(pos<=mid) change(ls,l,mid,pos,val);
else change(rs,mid+1,r,pos,val);
}
int query_pre(int o,int l,int r,int x,int y,int val){
if(x<=l&&r<=y) return bt.t[bt.pre(val,o)].val;
int mid=l+r>>1,res=-inf;
if(x<=mid) res=max(res,query_pre(ls,l,mid,x,y,val));
if(mid<y) res=max(res,query_pre(rs,mid+1,r,x,y,val));
return res;
}
int query_nxt(int o,int l,int r,int x,int y,int val){
if(x<=l&&r<=y) return bt.t[bt.nxt(val,o)].val;
int mid=l+r>>1,res=inf;
if(x<=mid) res=min(res,query_nxt(ls,l,mid,x,y,val));
if(mid<y) res=min(res,query_nxt(rs,mid+1,r,x,y,val));
return res;
}
int query_rank(int o,int l,int r,int x,int y,int val){
if(x<=l&&r<=y) return bt.rank(bt.root[o],val)-1;
int mid=l+r>>1,res=0;
if(x<=mid) res+=query_rank(ls,l,mid,x,y,val);
if(mid<y) res+=query_rank(rs,mid+1,r,x,y,val);
return res;
}
int query_kth(int x,int y,int k){
int l=0,r=100000005;
while(l<r){
int mid=l+r>>1;
int tmp=query_rank(1,1,n,x,y,mid);
if(tmp<k) l=mid+1;
else r=mid;
}
return l-1;
}
}tt;
void init(){
n=read(),m=read();
inc(i,1,n) a[i]=read();
tt.build(1,1,n);
}
void work(){
int opt,x,y,k,pos;
inc(i,1,m){
opt=read();
if(opt==1){
x=read(),y=read(),k=read();
printf("%d\n",tt.query_rank(1,1,n,x,y,k)+1);
}
if(opt==2){
x=read(),y=read(),k=read();
printf("%d\n",tt.query_kth(x,y,k));
}
if(opt==3){
pos=read(),k=read();
tt.change(1,1,n,pos,k);
}
if(opt==4){
x=read(),y=read(),k=read();
printf("%d\n",tt.query_pre(1,1,n,x,y,k));
}
if(opt==5){
x=read(),y=read(),k=read();
printf("%d\n",tt.query_nxt(1,1,n,x,y,k));
}
}
}
int main(){
init();
work();
}
可持久化平衡树
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define inf 2147483647
using namespace std;
const int MAXN=500005;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
return f*x;
}
int n,root[MAXN],opt,x;
struct fhq_treap{
struct node{
int ch[2],val,size,key;
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
}t[MAXN*50];
int cnt;
void pushup(int x){t[x].size=t[lc(x)].size+t[rc(x)].size+1;}
void newnode(int &x,int val){
t[x=++cnt].val=val,t[cnt].key=rand(),t[cnt].size=1;
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(t[x].key>t[y].key){
int tmp=++cnt;
t[tmp]=t[x];
rc(tmp)=merge(rc(tmp),y);
pushup(tmp);return tmp;
}
else{
int tmp=++cnt;
t[tmp]=t[y];
lc(tmp)=merge(x,lc(tmp));
pushup(tmp);return tmp;
}
}
void split(int tmp,int val,int &x,int &y){
if(!tmp) x=y=0;
else{
if(t[tmp].val<=val){
x=++cnt,t[x]=t[tmp];
split(rc(x),val,rc(x),y);
pushup(x);
}
else{
y=++cnt,t[y]=t[tmp];
split(lc(y),val,x,lc(y));
pushup(y);
}
}
}
void remove(int &tmp,int val){
int x=0,y=0,z=0;
split(tmp,val,x,z);
split(x,val-1,x,y);
y=merge(lc(y),rc(y));
tmp=merge(merge(x,y),z);
}
void insert(int &tmp,int val){
int x=0,y=0,z=0;
split(tmp,val,x,y);
newnode(z,val);
tmp=merge(merge(x,z),y);
}
int getval(int x,int k){
if(t[lc(x)].size+1==k) return t[x].val;
else if(k<=t[lc(x)].size) return getval(lc(x),k);
else return getval(rc(x),k-t[lc(x)].size-1);
}
int getrank(int &tmp,int val){
int x,y;
split(tmp,val-1,x,y);
int res=t[x].size+1;
tmp=merge(x,y);
return res;
}
int getpre(int &tmp,int val){
int x,y,res;
split(tmp,val-1,x,y);
if(!x) return -inf;
int k=t[x].size;
res=getval(x,k);
tmp=merge(x,y);
return res;
}
int getnxt(int &tmp,int val){
int x,y,res;
split(tmp,val,x,y);
if(!y) return inf;
res=getval(y,1);
tmp=merge(x,y);
return res;
}
}tp;
int main(){
n=read();
inc(i,1,n){
root[i]=root[read()];
opt=read(),x=read();
if(opt==1) tp.insert(root[i],x);
if(opt==2) tp.remove(root[i],x);
if(opt==3) printf("%d\n",tp.getrank(root[i],x));
if(opt==4) printf("%d\n",tp.getval(root[i],x));
if(opt==5) printf("%d\n",tp.getpre(root[i],x));
if(opt==6) printf("%d\n",tp.getnxt(root[i],x));
}
}
link-cur-tree
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define fa(x) t[x].fa
#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
using namespace std;
const int MAXN=300005;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
return f*x;
}
struct node{
int ch[2],fa,val,flag;
}t[MAXN];
int n,m,ins,x,y,a[MAXN],st[MAXN],top,cnt;
bool check(int x){
return t[fa(x)].ch[1]==x;
}
bool nroot(int x){
return lc(fa(x))==x||rc(fa(x))==x;
}
void pushup(int x){
t[x].val=t[lc(x)].val^t[rc(x)].val^a[x];
}
void connect(int x,int fa,int type){
fa(x)=fa;
t[fa].ch[type]=x;
}
void pushdown(int x){
if(t[x].flag){
t[lc(x)].flag^=1;
t[rc(x)].flag^=1;
swap(lc(x),rc(x));
t[x].flag=0;
}
}
void rotate(int x){
int y=fa(x),z=fa(y),k=check(x),w=t[x].ch[k^1];
t[x].fa=z;
if(nroot(y)) connect(x,z,check(y));
connect(w,y,k);
connect(y,x,k^1);
pushup(y),pushup(x);
}
void splay(int x){
int k=x,top=0;
while(nroot(k)) st[++top]=k,k=fa(k);
st[++top]=k;
while(top) pushdown(st[top--]);
while(nroot(x)){
int y=fa(x);
if(nroot(y)){
if(check(x)==check(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
}
void access(int x){
int y=0;
while(x){
splay(x);
rc(x)=y;
pushup(x);
y=x;
x=fa(x);
}
}
void makeroot(int x){
access(x);
splay(x);
t[x].flag^=1;
pushdown(x);
}
int findroot(int x){
access(x);
splay(x);
while(lc(x)) pushdown(x),x=lc(x);
return x;
}
void split(int x,int y){
makeroot(x);
access(y);
splay(y);
}
void link(int x,int y){
makeroot(x);
if(findroot(y)!=x) fa(x)=y;
}
void cut(int x,int y){
makeroot(x);
if(findroot(y)==x&&fa(x)==y&&lc(y)==x&&!rc(x)){
fa(x)=t[y].ch[0]=0;
pushup(y);
}
}
int main(){
n=read(),m=read();
inc(i,1,n) a[i]=read();
inc(i,1,m){
ins=read(),x=read(),y=read();
if(ins==0) split(x,y),printf("%d\n",t[y].val);
if(ins==1) link(x,y);
if(ins==2) cut(x,y);
if(ins==3) splay(x),a[x]=y;
}
return 0;
}
动态dp
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
#define inf 2147483647
#define int long long
using namespace std;
const int MAXN=100005;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
return f*x;
}
int n,m,a,b,cnt,dep[MAXN],size[MAXN],f[MAXN][2],g[MAXN][2],seg[MAXN],rev[MAXN],fa[MAXN],top[MAXN],son[MAXN],val[MAXN],bot[MAXN],u,w,head[MAXN];
struct edge{
int to,nxt;
}e[MAXN<<1];
void add(int a,int b){
e[++cnt].to=b;
e[cnt].nxt=head[a];
head[a]=cnt;
}
void dfs1(int u,int ff){
dep[u]=dep[ff]+1,fa[u]=ff,size[u]=1;
for(re int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==ff) continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void dfs2(int u,int ff){
g[u][1]=val[u];
if(son[u]){
top[son[u]]=top[u];
seg[son[u]]=++seg[0];
rev[seg[0]]=son[u];
dfs2(son[u],u);
}
for(re int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(!top[v]){
top[v]=v;
seg[v]=++seg[0];
rev[seg[0]]=v;
dfs2(v,u);
g[u][0]+=max(f[v][0],f[v][1]);
g[u][1]+=f[v][0];
}
}
if(son[u]) bot[u]=bot[son[u]];
else bot[u]=u;
f[u][0]=g[u][0]+max(f[son[u]][0],f[son[u]][1]);
f[u][1]=g[u][1]+f[son[u]][0];
}
struct martix{
int m[2][2];
}tmp[MAXN];
martix operator*(martix a,martix b){
martix tmp;
tmp.m[0][0]=max(a.m[0][0]+b.m[0][0],a.m[0][1]+b.m[1][0]);
tmp.m[1][0]=max(a.m[1][0]+b.m[0][0],a.m[1][1]+b.m[1][0]);
tmp.m[0][1]=max(a.m[0][0]+b.m[0][1],a.m[0][1]+b.m[1][1]);
tmp.m[1][1]=max(a.m[1][0]+b.m[0][1],a.m[1][1]+b.m[1][1]);
return tmp;
}
struct tree{
int l,r;
martix data;
}t[MAXN<<2];
void pushup(int o){
t[o].data=t[o<<1].data*t[o<<1|1].data;
}
void build(int o,int l,int r){
t[o].l=l,t[o].r=r;
if(l==r){
tmp[l]=t[o].data=(martix){g[rev[l]][0],g[rev[l]][0],g[rev[l]][1],-inf};
return;
}
int mid=l+r>>1;
build(o<<1,l,mid),build(o<<1|1,mid+1,r);
pushup(o);
}
void change(int o,int p){
if(t[o].l==p&&t[o].r==p){
t[o].data=tmp[p];
return;
}
int mid=t[o].l+t[o].r>>1;
if(p<=mid) change(o<<1,p);
else change(o<<1|1,p);
pushup(o);
}
martix query(int o,int x,int y){
if(x<=t[o].l&&t[o].r<=y){
return t[o].data;
}
int mid=t[o].l+t[o].r>>1;
if(y<=mid) return query(o<<1,x,y);
if(x>mid) return query(o<<1|1,x,y);
return query(o<<1,x,y)*query(o<<1|1,x,y);
}
void modify(int u,int w){
tmp[seg[u]].m[1][0]+=(w-val[u]),val[u]=w;
while(u){
martix a=query(1,seg[top[u]],seg[bot[u]]);
change(1,seg[u]);
martix b=query(1,seg[top[u]],seg[bot[u]]);
u=fa[top[u]];
if(!u)break;
int x=seg[u];
int g0=a.m[0][0],g1=a.m[1][0],f0=b.m[0][0],f1=b.m[1][0];
tmp[x].m[0][0]=tmp[x].m[0][1]=tmp[x].m[0][0]+max(f1,f0)-max(g1,g0);
tmp[x].m[1][0]=tmp[x].m[1][0]+f0-g0;
}
}
signed main(){
n=read(),m=read();
inc(i,1,n) val[i]=read();
inc(i,2,n){
a=read(),b=read();
add(a,b),add(b,a);
}
dfs1(1,0);
top[1]=1,seg[1]=++seg[0],rev[seg[0]]=1;
dfs2(1,0);
build(1,1,n);
inc(i,1,m){
u=read(),w=read();
modify(u,w);
martix ans=query(1,seg[1],seg[bot[1]]);
printf("%lld\n",max(ans.m[0][0],ans.m[1][0]));
}
}
可并堆
#include<bits/stdc++.h>
#define re register
#define inc(i,j,k) for(re int i=j;i<=k;i++)
using namespace std;
const int MAXN=100005;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while('0'<=ch&&ch<='9'){x=x*10+ch-'0',ch=getchar();}
return f*x;
}
int n,m,val[MAXN],ch[MAXN][2],dis[MAXN],fa[MAXN],ins,x,y;
int getfa(int x){
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
int merge(int x,int y){
if(x==0||y==0) return x+y;
if(val[x]>val[y]||(val[x]==val[y]&&x>y)) swap(x,y);
ch[x][1]=merge(ch[x][1],y);
if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]);
dis[x]=dis[ch[x][1]]+1;
fa[ch[x][0]]=fa[ch[x][1]]=x;
return x;
}
int pop(int x){
int tmp=val[x];val[x]=-1;
fa[ch[x][0]]=ch[x][0];
fa[ch[x][1]]=ch[x][1];
fa[x]=merge(ch[x][0],ch[x][1]);
return tmp;
}
int main(){
n=read(),m=read();
inc(i,1,n) val[i]=read(),fa[i]=i;
inc(i,1,m){
ins=read();
if(ins==1){
x=read(),y=read();
if(val[x]==-1||val[y]==-1) continue;
int fx=getfa(x),fy=getfa(y);
if(fx==fy) continue;
merge(fx,fy);
}
else{
x=read();
if(val[x]==-1){
puts("-1");
continue;
}
int fx=getfa(x);
printf("%d\n",pop(fx));
}
}
}
min_25筛
#include<bits/stdc++.h>
#define re register
#define ll long long
#define inc(i,j,k) for(re ll i=j;i<=k;i++)
using namespace std;
const int mod=1e9+7;
const int inv2=5e8+4;
const int inv6=166666668;
const int N=1e6+5;
inline ll read(){
ll x=0;
char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
int len,tot,id1[N],id2[N],cnt;
ll prime[N],sp1[N],sp2[N];
ll n,g1[N],g2[N],w[N];
bool check[N];
void init(int n){
inc(i,2,n){
if(!check[i]){
prime[++tot]=i;
sp1[tot]=(sp1[tot-1]+i)%mod;
sp2[tot]=(sp2[tot-1]+1LL*i*i)%mod;
}
inc(j,1,tot){
if(i*prime[j]>n) break;
check[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
ll s(ll i,int j){
if(prime[j]>=i) return 0;
int u=i<=len?id1[i]:id2[n/i];
ll ans=(g2[u]-g1[u]-sp2[j]+sp1[j]+2*mod)%mod;
inc(p,j+1,tot){
if(prime[p]*prime[p]>i) break;
ll pe=prime[p];
for(re int e=1;pe<=i;e++,pe=pe*prime[p]){
ll cur=pe%mod;
(ans+=cur*(cur-1)%mod*(s(i/pe,p)+(e!=1))%mod)%=mod;
}
}
return ans;
}
int main(){
n=read();len=sqrt(n);init(len);
for(re ll l=1,r;l<=n;l=r+1){
r=n/(n/l),w[++cnt]=n/l;
ll cur=w[cnt]%mod;
g1[cnt]=cur*(cur+1)%mod*inv2%mod;
g2[cnt]=cur*(cur+1)%mod*(2*cur+1)%mod*inv6%mod;
(g1[cnt]+=mod-1)%=mod,(g2[cnt]+=mod-1)%=mod;
if(n/l<=len) id1[n/l]=cnt;
else id2[n/(n/l)]=cnt;
}
inc(i,1,tot){
inc(j,1,cnt){
if(prime[i]*prime[i]>w[j]) break;
int u=w[j]/prime[i]<=len?id1[w[j]/prime[i]]:id2[n/(w[j]/prime[i])];
(g1[j]+=mod-prime[i]*(g1[u]-sp1[i-1]+mod)%mod)%=mod;
(g2[j]+=mod-prime[i]*prime[i]%mod*(g2[u]-sp2[i-1]+mod)%mod)%=mod;
}
}
printf("%lld",(s(n,0)+1)%mod);
return 0;
}