板子库
CSP-S 2023 试机
- 线段树pushdown l,r写反了
- 线段树query t[k].l写成l,r也是
- ST表query
st[r-(1<<s)+1][s]
- 线性阶乘逆元
inv[i]=inv[i+1] * (i+1) % mod
NOIP2023 试机
- 线段树
k<<1写成k>>1 - 线段树query
t[k].l写成l,r也是 - ST表查询
ans=max(st[l][s],st[r-(1<<s)+1][s]) - 线性筛
if(i%prime[j]==0) break;写成if(i%prime[j]) break;
CSP2024 试机
完美
常用杂项
对拍
#include<bits/stdc++.h>
using namespace std;
int main(){
for(int i=1;i<=1e9;i++){
system("makedata.exe");
system("a.exe");
system("b.exe");
if(system("fc a.out b.out")) break;
printf("AC #%d\n",i);
}
return 0;
}
缺省源
#include<bits/stdc++.h>
#define MAXN 100005
#define mod 998244353
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
bool M2;
signed main(){
// freopen("","r",stdin);
// freopen("","w",stdout);
int Time=clock();
look_memory;
look_time;
return 0;
}
卡时
if((double)clock()/CLOCKS_PER_SEC > 0.98) break;
函数
-
popcnt:
__builtin_popcount(sta) -
归并排序:
inplace_merge(a+l,a+mid+1,a+r+1,cmp) -
线性中位数:
nth_element(a+l,a+mid,a+r+1,cmp) -
全排列:
next_permutation(a+1,a+1+n)
数据结构
线段树
/*
基础线段树 区间加区间求和 带lazytag
*/
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
long long a[MAXN];
struct node{
int l,r;
long long val,tag;
}t[MAXN<<2];
void pushup(int k){
t[k].val=t[k<<1].val+t[k<<1|1].val;
}
void pushdown(int k){
if(t[k].tag!=0){
t[k<<1].val+=(t[k<<1].r-t[k<<1].l+1)*t[k].tag;
t[k<<1].tag+=t[k].tag;
t[k<<1|1].val+=(t[k<<1|1].r-t[k<<1|1].l+1)*t[k].tag;
t[k<<1|1].tag+=t[k].tag;
t[k].tag=0;
}
}
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
if(l==r){
t[k].val=a[l];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
return;
}
void update(int k,int l,int r,int v){
if(t[k].l>=l && t[k].r<=r){
t[k].val+=(t[k].r-t[k].l+1)*v;
t[k].tag+=v;
return;
}
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if(mid>=l){
update(k<<1,l,r,v);
}
if(mid<r){
update(k<<1|1,l,r,v);
}
pushup(k);
}
long long query(int k,int l,int r){
if(t[k].l>=l && t[k].r<=r){
return t[k].val;
}
long long res=0;
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if(mid>=l){
res+=query(k<<1,l,r);
}
if(mid<r){
res+=query(k<<1|1,l,r);
}
return res;
}
int main(){
//freopen("","r",stdin);
//freopen("","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
build(1,1,n);
int op,l,r,v;
while(m--){
op=read();
l=read();r=read();
if(op==1){
v=read();
update(1,l,r,v);
}else{
long long ans=query(1,l,r);
printf("%lld\n",ans);
}
}
return 0;
}
树状数组
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
int a[MAXN],c[MAXN];
int lowbit(int x){
return x&(-x);
}
void update(int x,int v){
while(x<=n){
c[x]+=v;
x+=lowbit(x);
}
}
int query(int x){
int res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
update(i,a[i]);
}
int op,x,y;
while(m--){
op=read();
x=read();y=read();
if(op==1){
update(x,y);
}else{
int ans=query(y)-query(x-1);
printf("%d\n",ans);
}
}
return 0;
}
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
int a[MAXN],c[MAXN];
int lowbit(int x){
return x&(-x);
}
void update(int x,int v){
while(x<=n){
c[x]+=v;
x+=lowbit(x);
}
}
int query(int x){
int res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
update(i,a[i]-a[i-1]);
}
int op,x,y,v;
while(m--){
op=read();
x=read();
if(op==1){
y=read();
v=read();
update(x,v);
update(y+1,-v);
}else{
int ans=query(x);
printf("%d\n",ans);
}
}
return 0;
}
ST表
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int st[MAXN][20];
int lg[MAXN],logn;
void init(){
lg[1]=0;
lg[2]=1;
for(int i=3;i<=n;i++){
lg[i]=lg[i>>1]+1;
}
logn=lg[n];
for(int j=1;j<=logn;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
}
int main(){
//freopen("","r",stdin);
//freopen("","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++){
st[i][0]=read();
}
init();
int l,r;
while(m--){
l=read();r=read();
int s=lg[r-l+1];
int ans=max(st[l][s],st[r-(1<<s)+1][s]);
printf("%d\n",ans);
}
return 0;
}
并查集 影子并查集
#include<bits/stdc++.h>
#define MAXN 50005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int fa[MAXN],val[MAXN];
int ans;
int find(int x){
if(x==fa[x]) return fa[x];
int f=fa[x];
fa[x]=find(fa[x]);
val[x]=(val[x]+val[f])%3;
return fa[x];
}
void merge(int x,int y){
x=find(x);
y=find(y);
fa[y]=x;
val[x]+=val[y];
}
int main(){
//freopen("","r",stdin);
//freopen("","w",stdout);
n=read();m=read();
for(int i=1;i<=n;i++){
fa[i]=i;
}
int op,x,y;
while(m--){
op=read();
x=read();y=read();
if(x>n || y>n || (op==2 && x==y)){
ans++;
continue;
}
int fx=find(x);
int fy=find(y);
if(op==1){
if(fx==fy){
if(val[x]!=val[y]) ans++;
}else{
fa[fx]=fy;
val[fx]=(val[y]-val[x]+3)%3;
}
}else{
if(fx==fy){
int tmp=(val[x]-val[y]+3)%3;
if(tmp!=1) ans++;
}else{
fa[fx]=fy;
val[fx]=(val[y]-val[x]+1+3)%3;
}
}
}
printf("%d",ans);
return 0;
}
堆
//小根堆
priority_queue <int,vector<int>,greater<int>> q1;
//大根堆
priority_queue <int,vector<int>,less<int>> q2;
//默认大根堆
priority_queue<int> q;
struct node{
int x;
bool operator < (node tmp) const{
return tmp.x<x;
}
};//tmp是this 这个是小根堆
priority_queue<node> myq;
左偏树(可并堆)
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
struct node{
int ls,rs;
int id,dis,val;
bool operator < (node x) const{
return val==x.val ? id<x.id : val<x.val;
}
}t[MAXN];
int fa[MAXN];
bool mark[MAXN];
int find(int x){
if(x==fa[x]) return fa[x];
return fa[x]=find(fa[x]);
}
int merge(int x,int y){
if(x*y==0) return x+y;
if(t[y]<t[x]) swap(x,y);
t[x].rs=merge(t[x].rs,y);
fa[t[x].rs]=x;
if(t[t[x].ls].dis<t[t[x].rs].dis) swap(t[x].ls,t[x].rs);
t[x].dis=t[t[x].rs].dis+1;
return x;
}
void pop(int x){
fa[t[x].ls]=fa[t[x].rs]=fa[x]=merge(t[x].ls,t[x].rs);
t[x].ls=t[x].rs=t[x].dis=0;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
t[i].val=read();
t[i].id=i;
fa[i]=i;
}
int op,x,y;
while(m--){
op=read();
if(op==1){
x=read();y=read();
if(mark[x] || mark[y]) continue;
x=find(x);y=find(y);
if(x!=y) fa[x]=fa[y]=merge(x,y);
}else{
x=read();
if(mark[x]){
puts("-1");
continue;
}
x=find(x);
printf("%d\n",t[x].val);
mark[x]=true;
pop(x);
}
}
return 0;
}
分块
李超线段树
#include<bits/stdc++.h>
#define MAXN 100005
#define mod 998244353
#define ls k<<1
#define rs k<<1|1
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n;
struct line{
double k,b;
}lin[MAXN];
int tot;
int t[MAXN<<2];
const int N=50000;
const double inf=1e9;
double get_val(int i,int x){
return lin[i].k*x+lin[i].b;
}
void update(int k,int l,int r,int x){
if(l==r){
if(get_val(x,l)>get_val(t[k],l)) t[k]=x;
return;
}
int mid=(l+r)>>1;
if(get_val(x,mid)>get_val(t[k],mid)) swap(t[k],x);
if(get_val(x,l)>get_val(t[k],l)) update(ls,l,mid,x);
if(get_val(x,r)>get_val(t[k],r)) update(rs,mid+1,r,x);
}
double query(int k,int l,int r,int x){
if(l==r) return get_val(t[k],x);
int mid=(l+r)>>1;
if(mid>=x) return max(get_val(t[k],x),query(ls,l,mid,x));
else return max(get_val(t[k],x),query(rs,mid+1,r,x));
}
bool M2;
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int Time=clock();
n=read();
char op[10];
double k,b;
int x;
while(n--){
scanf("%s",op);
if(op[0]=='P'){
scanf("%lf %lf",&b,&k);
lin[++tot]=(line){k,b-k};
update(1,1,N,tot);
}else{
x=read();
int ans=query(1,1,N,x);
printf("%d\n",ans/100);
}
}
look_memory;
look_time;
return 0;
}
平衡树
权值Treap
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,tot;
struct node{
int val,key;//权值,堆值
int ls,rs;//左右儿子编号
int sz;//大小,该元素数量
}t[MAXN];
int rt,x,y;
int get_new(int x){
tot++;
t[tot].val=x;
t[tot].key=rand();
t[tot].sz=1;
return tot;
}
void pushup(int k){
t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}
void split(int k,int &x,int &y,int ky){//分裂 将k中<=ky的分到x >ky的分到y
if(k==0){
x=y=0;
return;
}
if(t[k].val<=ky){
x=k;
split(t[k].rs,t[x].rs,y,ky);
}else{
y=k;
split(t[k].ls,x,t[y].ls,ky);
}
pushup(k);
}
void merge(int &k,int x,int y){//合并 将x和y合并为k
if(x*y==0){
k=x+y;
return;
}
if(t[x].key>t[y].key){
k=x;
merge(t[k].rs,t[x].rs,y);
}else{
k=y;
merge(t[k].ls,x,t[y].ls);
}
pushup(k);
}
int find(int num){
int now=rt;
while(true){
if(t[t[now].ls].sz==num-1){
return t[now].val;
}else if(t[t[now].ls].sz<num-1){
num-=t[t[now].ls].sz+1;
now=t[now].rs;
}else{
now=t[now].ls;
}
}
return 0;
}
int main(){
srand(time(0));
n=read();
int op,v;
while(n--){
op=read();
v=read();
if(op==1){
int nw=get_new(v);
split(rt,rt,x,v);
merge(rt,rt,nw);
merge(rt,rt,x);
}else if(op==2){
split(rt,rt,y,v);
split(rt,rt,x,v-1);
merge(x,t[x].ls,t[x].rs);
merge(rt,rt,x);
merge(rt,rt,y);
}else if(op==3){
split(rt,rt,x,v-1);
printf("%d\n",t[rt].sz+1);
merge(rt,rt,x);
}else if(op==4){
printf("%d\n",find(v));
}else if(op==5){
split(rt,rt,x,v-1);
int now=rt;
while(t[now].rs) now=t[now].rs;
printf("%d\n",t[now].val);
merge(rt,rt,x);
}else if(op==6){
split(rt,rt,x,v);
int now=x;
while(t[now].ls) now=t[now].ls;
printf("%d\n",t[now].val);
merge(rt,rt,x);
}
}
return 0;
}
序列Treap
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
int a[MAXN];
struct node{
int val,key;//权值,堆值
int ls,rs;//左右儿子编号
int sz;
int ec;//exchange
}t[MAXN];
int rt,x,y;
void make_exchange(int k){
t[k].ec^=1;
swap(t[k].ls,t[k].rs);
}
void pushup(int k){
t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}
void pushdown(int k){
if(t[k].ec){
make_exchange(t[k].ls);
make_exchange(t[k].rs);
t[k].ec=0;
}
}
void split(int k,int &x,int &y,int ky){
if(k==0){
x=y=0;
return;
}
pushdown(k);
if(t[t[k].ls].sz+1<=ky){
x=k;
split(t[k].rs,t[x].rs,y,ky-t[t[k].ls].sz-1);
}else{
y=k;
split(t[k].ls,x,t[y].ls,ky);
}
pushup(k);
}
void merge(int &k,int x,int y){
if(x*y==0){
k=x+y;
return;
}
if(t[x].key>t[y].key){
k=x;
pushdown(k);
merge(t[k].rs,t[x].rs,y);
}else{
k=y;
pushdown(k);
merge(t[k].ls,x,t[y].ls);
}
pushup(k);
}
void dfs(int k){
if(k==0) return;
pushdown(k);
dfs(t[k].ls);
printf("%d ",t[k].val);
dfs(t[k].rs);
}
int main(){
srand(time(0));
n=read();m=read();
for(int i=1;i<=n;i++){
t[i].val=i;
t[i].sz=1;
t[i].key=rand();
merge(rt,rt,i);
}
int l,r;
while(m--){
l=read();r=read();
split(rt,rt,y,r);
split(rt,rt,x,l-1);
make_exchange(x);
merge(rt,rt,x);
merge(rt,rt,y);
}
dfs(rt);
return 0;
}
权值Splay
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n;
int ch[MAXN][5],fa[MAXN],val[MAXN],cnt[MAXN],sz[MAXN];
//0表示左儿子 1表示右儿子
int rt,tot;
const int inf=0x7fffffff;
int get_new(int v){
tot++;
fa[tot]=ch[tot][0]=ch[tot][1]=0;
val[tot]=v;
cnt[tot]=sz[tot]=1;
return tot;
}
void pushup(int x){
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}
//加入inf和-inf 便于操作
void init(){
int x=get_new(-inf);
int y=get_new(inf);
fa[y]=x;
ch[x][1]=y;
rt=x;
pushup(y);
pushup(x);
}
void rotate(int x){
int y=fa[x],z=fa[y];
int k=(ch[y][1]==x);//x是左儿子还是右儿子
int w=ch[x][k^1];//旋转后左儿子变右儿子,右儿子变左儿子
if(z) ch[z][ch[z][1]==y]=x;
fa[x]=z;
fa[fa[ch[ch[x][k^1]=y][k]=w]=y]=x;
pushup(y);
pushup(x);
}
//每次在树上遍历都要splay! 才能保证均摊复杂度
void splay(int x,int gl){
while(fa[x]!=gl){
int y=fa[x],z=fa[y];
if(z!=gl){
if((ch[y][1]==x)==(ch[z][1]==y)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(gl==0) rt=x;
}
//w这个结点,返回的是结点编号;没有,返回的是前驱或者后继。
int get_id(int v){
int x=rt;
while(val[x]!=v && ch[x][v>val[x]]){
x=ch[x][v>val[x]];
}
splay(x,0);
return x;
}
//找到权值为v的数的前驱的编号
int get_pre(int v){
int x=get_id(v);
if(val[x]<v) return x;
splay(x,0);
x=ch[x][0];
while(ch[x][1]) x=ch[x][1];
splay(x,0);
return x;
}
//找到权值为v的数的后继的编号
int get_suf(int v){
int x=get_id(v);
if(val[x]>v) return x;
splay(x,0);
x=ch[x][1];
while(ch[x][0]) x=ch[x][0];
splay(x,0);
return x;
}
void Insert(int v){
int x=rt,y;
while(x && val[x]!=v){
y=x;
x=ch[x][v>val[x]];
}
if(x){
cnt[x]++;
}else{
x=get_new(v);
fa[x]=y;
ch[y][v>val[y]]=x;
}
splay(x,0);
}
void Delete(int v){
int suf=get_suf(v);
int pre=get_pre(v);
splay(pre,0);
splay(suf,pre);
int x=ch[suf][0];
if(x==0) return;
cnt[x]--;
pushup(x);
if(cnt[x]==0) ch[suf][0]=0;
pushup(suf);
pushup(pre);
}
int get_kth(int v){
int x=get_id(v);
splay(x,0);
return sz[ch[x][0]]+(val[x]<v)*cnt[x]+1;
}
int get_val(int k){
int x=rt;
while(true){
if(sz[ch[x][0]]>=k){
x=ch[x][0];
}else if(sz[ch[x][0]]+cnt[x]<k){
k-=sz[ch[x][0]]+cnt[x];
x=ch[x][1];
}else{
splay(x,0);
return val[x];
}
}
}
int main(){
init();
n=read();
int op,v;
while(n--){
op=read();
v=read();
if(op==1){
Insert(v);
}else if(op==2){
Delete(v);
}else if(op==3){
printf("%d\n",get_kth(v)-1);//因为插入了-inf 所以实际要-1
}else if(op==4){
printf("%d\n",get_val(v+1));//同理
}else if(op==5){
printf("%d\n",val[get_pre(v)]);
}else{
printf("%d\n",val[get_suf(v)]);
}
}
return 0;
}
序列Splay
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
int fa[MAXN],ch[MAXN][5], val[MAXN],sz[MAXN],rv[MAXN];
int rt,tot;
const int inf=0x7fffffff;
int get_new(int v){
tot++;
fa[tot]=ch[tot][0]=ch[tot][1]=0;
rv[tot]=0;
sz[tot]=1;
val[tot]=v;
return tot;
}
void pushup(int x){
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}
void init(){
int x=get_new(inf);
int y=get_new(-inf);
rt=x;
ch[x][0]=y;
fa[y]=x;
pushup(y);
pushup(x);
}
void rotate(int x){
int y=fa[x],z=fa[y];
int k=(ch[y][1]==x);
int w=ch[x][k^1];
if(z) ch[z][ch[z][1]==y]=x;
fa[x]=z;
fa[fa[ch[ch[x][k^1]=y][k]=w]=y]=x;
pushup(y);
pushup(x);
}
void splay(int x,int gl){
while(fa[x]!=gl){
int y=fa[x],z=fa[y];
if(z!=gl){
if((ch[y][1]==x)==(ch[z][1]==y)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(gl==0) rt=x;
}
void make_rv(int x){
rv[x]^=1;
swap(ch[x][0],ch[x][1]);
}
void pushdown(int x){
if(rv[x]){
make_rv(ch[x][0]);
make_rv(ch[x][1]);
rv[x]=0;
}
}
int get_id(int k){
int x=rt;
while(true){
//printf("!%d ",x);
pushdown(x);
if(sz[ch[x][0]]>=k){
x=ch[x][0];
}else if(sz[ch[x][0]]+1<k){
k-=sz[ch[x][0]]+1;
x=ch[x][1];
}else{
splay(x,0);
return x;
}
}
}
void Insert(int v,int x){
int pre=get_id(x);//-inf 实际代表k-1
int suf=get_id(x+1);
//puts("!");
splay(pre,0);
splay(suf,pre);
ch[suf][0]=get_new(v);
fa[ch[suf][0]]=suf;
//puts("!");
pushup(x);
pushup(suf);
pushup(pre);
//puts("!");
}
void calc(int l,int r){
int pre=get_id(l-1);
int suf=get_id(r+1);
splay(pre,0);
splay(suf,pre);
make_rv(ch[suf][0]);
pushup(suf);
pushup(pre);
}
void dfs(int x){
if(x==0) return;
pushdown(x);
dfs(ch[x][0]);
if(val[x]<=n && val[x]>=1) printf("%d ",val[x]);
dfs(ch[x][1]);
}
int main(){
init();
n=read();m=read();
for(int i=1;i<=n;i++){
//printf("%d ",i);
Insert(i,i);
}
int l,r;
while(m--){
l=read();r=read();
calc(l+1,r+1);//-inf
}
dfs(rt);
return 0;
}
可持久化序列线段树
#include<bits/stdc++.h>
#define MAXN 1000005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
int a[MAXN];
struct node{
int ls,rs;
int val;
}t[MAXN<<5];
int rt[MAXN],tot;
void build(int &k,int l,int r){
k=++tot;
if(l==r){
t[k].val=a[l];
return;
}
int mid=(l+r)>>1;
build(t[k].ls,l,mid);
build(t[k].rs,mid+1,r);
}
void update(int &k,int pre,int l,int r,int p,int v){
k=++tot;
t[k]=t[pre];
if(l==r){
t[k].val=v;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(t[k].ls,t[pre].ls,l,mid,p,v);
else update(t[k].rs,t[pre].rs,mid+1,r,p,v);
}
int query(int k,int l,int r,int p){
if(l==r){
return t[k].val;
}
int mid=(l+r)>>1;
if(mid>=p) return query(t[k].ls,l,mid,p);
else return query(t[k].rs,mid+1,r,p);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
build(rt[0],1,n);
int pre,op,x,v;
for(int i=1;i<=m;i++){
pre=read();op=read();
if(op==1){
x=read();v=read();
update(rt[i],rt[pre],1,n,x,v);
}else{
x=read();
printf("%d\n",query(rt[pre],1,n,x));
rt[i]=rt[pre];
}
}
}
//请保持心脏震动,等待有人与你共鸣
可持久化权值线段树(主席树)
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
int a[MAXN],lsh[MAXN],nn,aa[MAXN];
struct node{
int ls,rs;
long long sum;
}t[MAXN<<5];
int rt[MAXN],tot;
void build(int &k,int l,int r){
k=++tot;
if(l==r) return;
int mid=(l+r)>>1;
build(t[k].ls,l,mid);
build(t[k].rs,mid+1,r);
}
void pushup(int k){
t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum;
}
void update(int &k,int pre,int l,int r,int p,int v){
k=++tot;
t[k]=t[pre];
if(l==r){
t[k].sum+=v;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(t[k].ls,t[pre].ls,l,mid,p,v);
if(mid<p) update(t[k].rs,t[pre].rs,mid+1,r,p,v);
pushup(k);
}
int query(int x,int y,int l,int r,int k){
if(l==r) return l;
int sum=t[t[y].ls].sum-t[t[x].ls].sum;
int mid=(l+r)>>1;
if(sum>=k) return query(t[x].ls,t[y].ls,l,mid,k);
else return query(t[x].rs,t[y].rs,mid+1,r,k-sum);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
lsh[i]=a[i];
}
sort(lsh+1,lsh+1+n);
nn=unique(lsh+1,lsh+1+n)-lsh-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(lsh+1,lsh+1+nn,a[i])-lsh;
}
build(rt[0],1,n);
for(int i=1;i<=n;i++){
update(rt[i],rt[i-1],1,nn,a[i],1);
}
int l,r,k;
while(m--){
l=read();r=read();k=read();
int ans=query(rt[l-1],rt[r],1,nn,k);
printf("%d\n",lsh[ans]);
}
return 0;
}
//保持心脏震动,有人等你共鸣
可持久化权值平衡树
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,tot;
struct node{
int val,key;//权值,堆值
int ls,rs;//左右儿子编号
int sz;//大小,该元素数量
}t[MAXN*50];
int rt[MAXN];
int get_new(int x){
tot++;
t[tot].val=x;
t[tot].key=rand();
t[tot].sz=1;
return tot;
}
void pushup(int k){
t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}
void split(int k,int &x,int &y,int ky){
if(k==0){
x=y=0;
return;
}
if(t[k].val<=ky){
x=get_new(0);
t[x]=t[k];
split(t[x].rs,t[x].rs,y,ky);
pushup(x);
}else{
y=get_new(0);
t[y]=t[k];
split(t[y].ls,x,t[y].ls,ky);
pushup(y);
}
}
int merge(int x,int y){
if(x*y==0){
return x+y;
}
if(t[x].key>t[y].key){
int k=get_new(0);
t[k]=t[x];
t[k].rs=merge(t[k].rs,y);
pushup(k);
return k;
}else{
int k=get_new(0);
t[k]=t[y];
t[k].ls=merge(x,t[k].ls);
pushup(k);
return k;
}
}
int find(int rt,int num){
int now=rt;
while(true){
if(t[t[now].ls].sz==num-1){
return t[now].val;
}else if(t[t[now].ls].sz<num-1){
num-=t[t[now].ls].sz+1;
now=t[now].rs;
}else{
now=t[now].ls;
}
}
return 0;
}
int main(){
srand(9907);
n=read();
int id,op,v;
int x,y,z;
for(int i=1;i<=n;i++){
id=read();op=read();v=read();
rt[i]=rt[id];
if(op==1){
int nw=get_new(v);
split(rt[i],x,y,v);
rt[i]=merge(merge(x,nw),y);
}else if(op==2){
split(rt[i],x,z,v);
split(x,x,y,v-1);
y=merge(t[y].ls,t[y].rs);
rt[i]=merge(merge(x,y),z);
}else if(op==3){
split(rt[i],x,y,v-1);
printf("%d\n",t[x].sz+1);
rt[i]=merge(x,y);
}else if(op==4){
printf("%d\n",find(rt[i],v));
}else if(op==5){
split(rt[i],x,y,v-1);
int now=x;
while(t[now].rs) now=t[now].rs;
printf("%d\n",t[now].val);
rt[i]=merge(x,y);
}else if(op==6){
split(rt[i],x,y,v);
int now=y;
while(t[now].ls) now=t[now].ls;
printf("%d\n",t[now].val);
rt[i]=merge(x,y);
}
}
return 0;
}
可持久化序列平衡树
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,tot;
struct node{
int ls,rs;
long long val,sum,tag;
int key,sz;
}t[MAXN*90];
int rt[MAXN];
int get_new(int v){
tot++;
t[tot].sum=t[tot].val=v;
t[tot].key=rand();
t[tot].sz=1;
return tot;
}
void make_exchange(int k){
t[k].tag^=1;
swap(t[k].ls,t[k].rs);
}
void pushup(int k){
t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum+t[k].val;
}
void pushdown(int k){
if(t[k].tag){
if(t[k].ls){
int tmp=get_new(0);
t[tmp]=t[t[k].ls];
t[k].ls=tmp;
make_exchange(t[k].ls);
}
if(t[k].rs){
int tmp=get_new(0);
t[tmp]=t[t[k].rs];
t[k].rs=tmp;
make_exchange(t[k].rs);
}
t[k].tag=0;
}
}
void split(int k,int &x,int &y,int ky){
// printf("%d %d %d %d\n",k,x,y,ky);
if(k==0){
x=y=0;
return;
}
pushdown(k);
if(t[t[k].ls].sz+1<=ky){
x=get_new(0);
t[x]=t[k];
split(t[x].rs,t[x].rs,y,ky-t[t[x].ls].sz-1);
pushup(x);
}else{
y=get_new(0);
t[y]=t[k];
split(t[y].ls,x,t[y].ls,ky);
pushup(y);
}
}
int merge(int x,int y){
if(x*y==0){
return x+y;
}
pushdown(x);
pushdown(y);
if(t[x].key>t[y].key){
int k=get_new(0);
t[k]=t[x];
// int k=x;
t[k].rs=merge(t[k].rs,y);
pushup(k);
return k;
}else{
int k=get_new(0);
t[k]=t[y];
// int k=y;
t[k].ls=merge(x,t[k].ls);
pushup(k);
return k;
}
}
int main(){
srand(9907);
n=read();
int id,op;
long long p,v,l,r;
long long ans=0;
int x,y,z;
for(int i=1;i<=n;i++){
id=read();op=read();
rt[i]=rt[id];
if(op==1){
p=read();v=read();
p^=ans;v^=ans;
int nw=get_new(v);
split(rt[i],x,y,p);
rt[i]=merge(merge(x,nw),y);
}else if(op==2){
p=read();
p^=ans;
split(rt[i],x,z,p);
split(x,x,y,p-1);
rt[i]=merge(x,z);
}else if(op==3){
l=read();r=read();
l^=ans;r^=ans;
split(rt[i],x,z,r);
split(x,x,y,l-1);
make_exchange(y);
rt[i]=merge(merge(x,y),z);
}else if(op==4){
l=read();r=read();
l^=ans;r^=ans;
// printf("l=%d r=%d\n",l,r);
split(rt[i],x,z,r);
split(x,x,y,l-1);
ans=t[y].sum;
printf("%lld\n",ans);
rt[i]=merge(merge(x,y),z);
}
}
return 0;
}
可持久化0-1trie
#include<bits/stdc++.h>
#define MAXN 600005
using namespace std;
inline long long read(){
long long x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m,tot;
int a[MAXN],sum[MAXN];
struct node{
int ch[2];
int val;
}t[MAXN*25];
int rt[MAXN];
void insert(int k,int pre,int v){
for(int i=25;i>=0;i--){
int s=(v>>i)&1;
t[k].ch[!s]=t[pre].ch[!s];
t[k].ch[s]=++tot;
t[t[k].ch[s]].val=t[t[pre].ch[s]].val+1;
k=t[k].ch[s];
pre=t[pre].ch[s];
}
}
int query(int x,int y,int v){
int res=0;
for(int i=25;i>=0;i--){
int s=(v>>i)&1;
// printf("! %d %d\n",t[t[y].ch[!s]].val,t[t[x].ch[!s]].val);
if(t[t[y].ch[!s]].val>t[t[x].ch[!s]].val){
res+=(1<<i);
x=t[x].ch[!s];
y=t[y].ch[!s];
}else{
x=t[x].ch[s];
y=t[y].ch[s];
}
}
return res;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
sum[i]=sum[i-1]^a[i];
rt[i]=++tot;
insert(rt[i],rt[i-1],sum[i]);
}
char op[5];
int l,r,x;
while(m--){
scanf("%s",op);
if(op[0]=='A'){
x=read();
a[++n]=x;
sum[n]=sum[n-1]^a[n];
rt[n]=++tot;
insert(rt[n],rt[n-1],sum[n]);
}else{
l=read();r=read();
x=read();
l--;r--;
int ans=0;
if(l==0) ans=max(query(0,rt[r],sum[n]^x),sum[n]^x);
else ans=query(rt[l-1],rt[r],sum[n]^x);
printf("%d\n",ans);
}
}
return 0;
}
可持久化并查集
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
struct node{
int ls,rs;
int val;
}t[MAXN<<5];
int rtfa[MAXN],rtdep[MAXN],tot;
void build(int &k,int l,int r){
k=++tot;
if(l==r){
t[k].val=l;
return;
}
int mid=(l+r)>>1;
build(t[k].ls,l,mid);
build(t[k].rs,mid+1,r);
}
void update(int &k,int pre,int l,int r,int p,int v){
k=++tot;
t[k]=t[pre];
if(l==r){
t[k].val=v;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(t[k].ls,t[pre].ls,l,mid,p,v);
if(mid<p) update(t[k].rs,t[pre].rs,mid+1,r,p,v);
}
int query(int k,int l,int r,int p){
if(l==r) return t[k].val;
int mid=(l+r)>>1;
if(mid>=p) return query(t[k].ls,l,mid,p);
if(mid<p) return query(t[k].rs,mid+1,r,p);
}
int find(int id,int x){
int fx=query(rtfa[id],1,n,x);
if(fx==x) return fx;
else return find(id,fx);
}
void merge(int id,int x,int y){
x=find(id-1,x);
y=find(id-1,y);
if(x==y){
rtfa[id]=rtfa[id-1];
rtdep[id]=rtdep[id-1];
return;
}
int depx=query(rtdep[id-1],1,n,x);
int depy=query(rtdep[id-1],1,n,y);
if(depx==depy){
update(rtfa[id],rtfa[id-1],1,n,y,x);
update(rtdep[id],rtdep[id-1],1,n,x,depx+1);
}else{
if(depx<depy) swap(x,y);
update(rtfa[id],rtfa[id-1],1,n,y,x);
rtdep[id]=rtdep[id-1];
}
}
int main(){
n=read();m=read();
build(rtfa[0],1,n);
int op,a,b;
for(int i=1;i<=m;i++){
op=read();
if(op==1){
a=read();b=read();
merge(i,a,b);
}else if(op==2){
a=read();
rtfa[i]=rtfa[a];
rtdep[i]=rtdep[a];
}else{
a=read();b=read();
rtfa[i]=rtfa[i-1];
rtdep[i]=rtdep[i-1];
a=find(i,a);
b=find(i,b);
if(a==b) puts("1");
else puts("0");
}
}
return 0;
}
序列线段树套权值平衡树
#include<bits/stdc++.h>
#define MAXN 50005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,tot;
int a[MAXN];
struct node{
int ls,rs;
int val,key,sz;
}t[MAXN*100];
struct FHQ_Treap{
int rt,x,y,z;
int get_new(int v){
tot++;
t[tot].val=v;
t[tot].key=rand();
t[tot].sz=1;
return tot;
}
void pushup(int k){
t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;
}
void split(int k,int &x,int &y,int ky){
if(!k){
x=y=0;
return;
}
if(t[k].val<=ky){
x=k;
split(t[k].rs,t[x].rs,y,ky);
}else{
y=k;
split(t[k].ls,x,t[y].ls,ky);
}
pushup(k);
}
int merge(int x,int y){
if(x*y==0){
return x+y;
}
int k;
if(t[x].key>t[y].key){
k=x;
t[k].rs=merge(t[x].rs,y);
}else{
k=y;
t[k].ls=merge(x,t[y].ls);
}
pushup(k);
return k;
}
void insert(int v){
int nw=get_new(v);
split(rt,x,y,v);
rt=merge(merge(x,nw),y);
}
void Delete(int v){
split(rt,x,z,v);
split(x,x,y,v-1);
y=merge(t[y].ls,t[y].rs);
rt=merge(merge(x,y),z);
}
int get_rank(int v){
split(rt,x,y,v-1);
int res=t[x].sz+1;
rt=merge(x,y);
return res;
}
int get_pre(int v){
split(rt,x,y,v-1);
int res;
if(!x){
res=-2147483647;
}else{
int now=x;
while(t[now].rs) now=t[now].rs;
res=t[now].val;
}
rt=merge(x,y);
return res;
}
int get_suf(int v){
split(rt,x,y,v);
int res;
if(!y){
res=2147483647;
}else{
int now=y;
while(t[now].ls) now=t[now].ls;
res=t[now].val;
}
rt=merge(x,y);
return res;
}
}BT[MAXN<<2];
struct segment_tree{
#define ls k<<1
#define rs k<<1|1
struct node{
int l,r;
}t[MAXN<<2];
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
for(int i=l;i<=r;i++){
BT[k].insert(a[i]);
}
if(l==r) return;
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void update(int k,int p,int v){
BT[k].Delete(a[p]);
BT[k].insert(v);
if(t[k].l==t[k].r) return;
int mid=(t[k].l+t[k].r)>>1;
if(mid>=p) update(ls,p,v);
if(mid<p) update(rs,p,v);
}
int get_rank(int k,int l,int r,int v){
if(t[k].l>=l && t[k].r<=r){
return BT[k].get_rank(v)-1;
}
int mid=(t[k].l+t[k].r)>>1;
int res=0;
if(mid>=l) res+=get_rank(ls,l,r,v);
if(mid<r) res+=get_rank(rs,l,r,v);
return res;
}
int get_val(int L,int R,int v){
int l=0,r=1e8,mid;
int res=0;
while(l<=r){
mid=(l+r)>>1;
int num=get_rank(1,L,R,mid)+1;
if(num<=v){
res=mid;
l=mid+1;
}else{
r=mid-1;
}
}
return res;
}
int get_pre(int k,int l,int r,int v){
if(t[k].l>=l && t[k].r<=r){
return BT[k].get_pre(v);
}
int mid=(t[k].l+t[k].r)>>1;
int res=-2147483647;
if(mid>=l) res=max(res,get_pre(ls,l,r,v));
if(mid<r) res=max(res,get_pre(rs,l,r,v));
return res;
}
int get_suf(int k,int l,int r,int v){
if(t[k].l>=l && t[k].r<=r){
return BT[k].get_suf(v);
}
int mid=(t[k].l+t[k].r)>>1;
int res=2147483647;
if(mid>=l) res=min(res,get_suf(ls,l,r,v));
if(mid<r) res=min(res,get_suf(rs,l,r,v));
return res;
}
#undef ls
#undef rs
}ST;
int main(){
srand(time(0));
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
ST.build(1,1,n);
int op,l,r,k,p;
while(m--){
op=read();
if(op==1){
l=read();r=read();k=read();
printf("%d\n",ST.get_rank(1,l,r,k)+1);
}else if(op==2){
l=read();r=read();k=read();
printf("%d\n",ST.get_val(l,r,k));
}else if(op==3){
p=read();k=read();
ST.update(1,p,k);
a[p]=k;
}else if(op==4){
l=read();r=read();k=read();
printf("%d\n",ST.get_pre(1,l,r,k));
}else{
l=read();r=read();k=read();
printf("%d\n",ST.get_suf(1,l,r,k));
}
}
}
//祝你先于春天,翻过此间铮铮山峦
序列树状数组套权值线段树
#include<bits/stdc++.h>
#define MAXN 20005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,tot;
int a[MAXN],lsh[MAXN],nn;
struct node{
int ls,rs;
int sz;
}t[MAXN*100];
int rt[MAXN];
struct segment_tree{//权值线段树
void pushup(int k){
t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz;
}
void update(int &k,int l,int r,int p,int v){
if(!k) k=++tot;
if(l==r){
t[k].sz+=v;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(t[k].ls,l,mid,p,v);
if(mid<p) update(t[k].rs,mid+1,r,p,v);
pushup(k);
}
int query(int k,int l,int r,int L,int R){
if(!k) return 0;
if(l>=L && r<=R){
return t[k].sz;
}
int mid=(l+r)>>1;
int res=0;
if(mid>=L) res+=query(t[k].ls,l,mid,L,R);
if(mid<R) res+=query(t[k].rs,mid+1,r,L,R);
return res;
}
}ST;
struct tree_array{//序列树状数组
int lowbit(int x){
return x&(-x);
}
void update(int x,int p,int v){
for(;x<=n;x+=x&(-x)){
ST.update(rt[x],1,nn,p,v);
}
}
int ask(int x,int l,int r){
int res=0;
for(;x;x-=x&(-x)){
res+=ST.query(rt[x],1,nn,l,r);
}
return res;
}
int query(int l,int r,int nl,int nr){
if(r<l) return 0;
if(nr<nl) return 0;
int res=ask(r,nl,nr)-ask(l-1,nl,nr);
return res;
}
}BIT;
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
lsh[i]=a[i];
}
sort(lsh+1,lsh+1+n);
nn=unique(lsh+1,lsh+1+n)-lsh-1;
int ans=0;
for(int i=1;i<=n;i++){
a[i]=lower_bound(lsh+1,lsh+1+nn,a[i])-lsh;
BIT.update(i,a[i],1);
ans+=BIT.query(1,i-1,a[i]+1,nn);
}
printf("%d\n",ans);
m=read();
int x,y;
while(m--){
x=read();y=read();
if(x>y) swap(x,y);
ans-=BIT.query(x+1,y-1,1,a[x]-1);
ans+=BIT.query(x+1,y-1,a[x]+1,nn);
ans-=BIT.query(x+1,y-1,a[y]+1,nn);
ans+=BIT.query(x+1,y-1,1,a[y]-1);
if(a[x]<a[y]) ans++;
if(a[x]>a[y]) ans--;
BIT.update(x,a[x],-1);
BIT.update(x,a[y],1);
BIT.update(y,a[x],1);
BIT.update(y,a[y],-1);
swap(a[x],a[y]);
printf("%d\n",ans);
}
return 0;
}
//醉后不知天在水,满船清梦压星河
点分治
#include<bits/stdc++.h>
#define MAXN 10005
using namespace std;
inline long long read(){
long long x=0;
char c=0;
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
struct node{
int to,val;
};
vector<node> edge[MAXN];
int sz[MAXN],wt[MAXN];
int root,SZ;
bool vis[MAXN];
int dis[MAXN],tmp[MAXN],cnt;
int q[MAXN];
struct nd{
int dis;
int id,belong;
}a[MAXN];
bool ans[MAXN];
void get_root(int x,int f){
sz[x]=1;
wt[x]=0;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i].to;
if(y==f || vis[y]) continue;
get_root(y,x);
sz[x]+=sz[y];
wt[x]=max(wt[x],sz[y]);
}
wt[x]=max(wt[x],SZ-sz[x]);
if(wt[x]<wt[root]){
root=x;
}
return;
}
void get_dis(int x,int f,int sum,int from){
a[++cnt].dis=sum;
a[cnt].id=x;
a[cnt].belong=from;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i].to;
int w=edge[x][i].val;
if(y==f || vis[y]) continue;
get_dis(y,x,sum+w,from);
}
return;
}
bool cmp(nd aa,nd bb){
return aa.dis<bb.dis;
}
void calc(int x){
cnt=0;
a[++cnt].dis=0;
a[cnt].id=x;
a[cnt].belong=x;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i].to;
int w=edge[x][i].val;
if(vis[y]) continue;
get_dis(y,x,w,y);
}
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=m;i++){
if(ans[i]) continue;
int l=1,r=cnt;
while(l<r){
if(a[l].dis+a[r].dis>q[i]){
r--;
}else if(a[l].dis+a[r].dis<q[i]){
l++;
}else{
if(a[l].belong==a[r].belong){
if(a[l].dis==a[l+1].dis) l++;
else r--;
}else{
ans[i]=true;
break;
}
}
}
}
return;
}
void Divide(int x){
vis[x]=true;
calc(x);
int Sz=SZ;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i].to;
if(vis[y]) continue;
SZ=(sz[y]<sz[x]) ? sz[y] : (Sz-sz[x]);
root=0;
get_root(y,0);
Divide(root);
}
return;
}
int main(){
n=read();m=read();
int u,v,w;
for(int i=1;i<n;i++){
u=read();v=read();w=read();
edge[u].push_back((node){v,w});
edge[v].push_back((node){u,w});
}
for(int i=1;i<=m;i++){
q[i]=read();
}
wt[0]=n;
SZ=n;
get_root(1,0);
Divide(root);
for(int i=1;i<=m;i++){
if(ans[i]) puts("AYE");
else puts("NAY");
}
return 0;
}
点分树
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int a[MAXN];
vector<int> edge[MAXN];
int dep[MAXN],sz[MAXN],wt[MAXN],SZ,rt;
bool vis[MAXN];
int fa[MAXN],ffa[MAXN][25];
vector<int> cs[MAXN],cf[MAXN];
void dfs(int x,int f){
ffa[x][0]=f;
dep[x]=dep[f]+1;
for(auto y:edge[x]){
if(y==f) continue;
dfs(y,x);
}
}
void init(){
for(int j=1;j<=21;j++){
for(int i=1;i<=n;i++){
ffa[i][j]=ffa[ffa[i][j-1]][j-1];
}
}
}
int LCA(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int step=dep[a]-dep[b];
for(int i=0;i<=20;i++){
if(step&(1<<i)){
a=ffa[a][i];
}
}
if(a==b) return a;
for(int i=20;i>=0;i--){
if(ffa[a][i]!=ffa[b][i]){
a=ffa[a][i];
b=ffa[b][i];
}
}
return ffa[a][0];
}
int get_dis(int u,int v){
int lca=LCA(u,v);
return dep[u]+dep[v]-2*dep[lca];
}
int lowbit(int x){
return x&(-x);
}
void update(int op,int id,int x,int v){
int nn=op ? cs[id].size() : cf[id].size();
for(;x<nn;x+=lowbit(x)){
if(op==1) cs[id][x]+=v;
else cf[id][x]+=v;
}
}
int query(int op,int id,int x){
int res=0;
x=min(x,op?(int)cs[id].size()-1:(int)cf[id].size()-1);
for(;x>0;x-=lowbit(x)){
if(op==1) res+=cs[id][x];
else res+=cf[id][x];
}
return res;
}
void upd(int x,int v){
int p=x;
while(p){
update(1,p,get_dis(x,p)+1,v);
if(fa[p]) update(0,p,get_dis(x,fa[p])+1,v);
p=fa[p];
}
}
int ask(int x,int y){
int res=0;
int p=x;
while(p){
res+=query(1,p,y-get_dis(x,p)+1);
if(fa[p]) res-=query(0,p,y-get_dis(fa[p],x)+1);
p=fa[p];
}
return res;
}
void get_sz(int x,int f){
sz[x]=1;
for(auto y:edge[x]){
if(y==f || vis[y]) continue;
get_sz(y,x);
sz[x]+=sz[y];
}
}
void get_rt(int x,int f){
wt[x]=0;
for(auto y:edge[x]){
if(y==f || vis[y]) continue;
get_rt(y,x);
wt[x]=max(wt[x],sz[y]);
}
wt[x]=max(wt[x],SZ-sz[x]);
if(wt[x]<wt[rt]) rt=x;
}
int daco(int x){
get_sz(x,0);
SZ=sz[x],rt=0;
get_rt(x,0);
int r=rt;
vis[r]=true;
cs[r].resize(SZ+2);
cf[r].resize(SZ+2);
for(auto y:edge[r]){
if(vis[y]) continue;
int tmp=daco(y);
fa[tmp]=r;
}
return r;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
int u,v;
for(int i=1;i<n;i++){
u=read();v=read();
edge[v].push_back(u);
edge[u].push_back(v);
}
dfs(1,0);
init();
wt[0]=n;
daco(1);
for(int i=1;i<=n;i++){
upd(i,a[i]);
}
int op,x,y;
int ans=0;
while(m--){
op=read();
x=read();y=read();
x^=ans;y^=ans;
if(op==0){
ans=ask(x,y);
printf("%d\n",ans);
}else{
upd(x,y-a[x]);
a[x]=y;
}
}
return 0;
}
K-D Tree
邻域查询(算法复杂度没有保证 最坏 \(O(n)\))
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n;
struct point{
double x[2];
}a[MAXN];
struct node{
int ls,rs;
point x;
double D[2],U[2];
int id;
}t[MAXN];
int tot,rt;
double ans1=1e9,ans2;
const double inf=1ll<<32;
double mn=inf,mx;
bool cmp0(point aa,point bb){
return aa.x[0]<bb.x[0];
}
bool cmp1(point aa,point bb){
return aa.x[1]<bb.x[1];
}
void pushup(int k){
for(int i=0;i<=1;i++){
t[k].D[i]=min(t[k].x.x[i],min(t[t[k].ls].D[i],t[t[k].rs].D[i]));
t[k].U[i]=max(t[k].x.x[i],max(t[t[k].ls].U[i],t[t[k].rs].U[i]));
}
}
void build(int &k,int l,int r,int dm){
if(l>r) return;
k=++tot;
int mid=(l+r)>>1;
if(!dm) nth_element(a+l,a+mid,a+r+1,cmp0);
else nth_element(a+l,a+mid,a+r+1,cmp1);
t[k].x=a[mid];
t[k].id=mid;
build(t[k].ls,l,mid-1,dm^1);
build(t[k].rs,mid+1,r,dm^1);
pushup(k);
}
double get_mndis(int k,point y){
double res=0;
for(int i=0;i<=1;i++){
if(y.x[i]<t[k].D[i]) res+=(t[k].D[i]-y.x[i])*(t[k].D[i]-y.x[i]);
if(y.x[i]>t[k].U[i]) res+=(y.x[i]-t[k].U[i])*(y.x[i]-t[k].U[i]);
}
return res;
}
double get_mxdis(int k,point y){
double res=0;
for(int i=0;i<=1;i++){
double tmp=max((t[k].D[i]-y.x[i])*(t[k].D[i]-y.x[i]),(y.x[i]-t[k].U[i])*(y.x[i]-t[k].U[i]));
res+=tmp;
}
return res;
}
double get_dis(point x,point y){
double res=0;
for(int i=0;i<=1;i++){
res+=(x.x[i]-y.x[i])*(x.x[i]-y.x[i]);
}
return res;
}
void query_min(int k,point p,int dm,int id){
if(!k) return;
if(get_mndis(k,p)>=mn) return;
double dis=get_dis(t[k].x,p);
double dis1=get_mndis(t[k].ls,p);
double dis2=get_mndis(t[k].rs,p);
if(t[k].id!=id) mn=min(mn,dis);
if(dis1<dis2){
if(dis1<mn) query_min(t[k].ls,p,dm^1,id);
if(dis2<mn) query_min(t[k].rs,p,dm^1,id);
}else{
if(dis2<mn) query_min(t[k].rs,p,dm^1,id);
if(dis1<mn) query_min(t[k].ls,p,dm^1,id);
}
}
void query_max(int k,point p,int dm,int id){
if(!k) return;
if(get_mxdis(k,p)<=mx) return;
double dis=get_dis(t[k].x,p);
double dis1=get_mxdis(t[k].ls,p);
double dis2=get_mxdis(t[k].rs,p);
if(t[k].id!=id) mx=max(mx,dis);
if(dis1>dis2){
if(dis1>mx) query_max(t[k].ls,p,dm^1,id);
if(dis2>mx) query_max(t[k].rs,p,dm^1,id);
}else{
if(dis2>mn) query_max(t[k].rs,p,dm^1,id);
if(dis1>mn) query_max(t[k].ls,p,dm^1,id);
}
}
int main(){
n=read();
for(int i=1;i<=n;i++){
scanf("%lf %lf",&a[i].x[0],&a[i].x[1]);
}
t[0].D[0]=t[0].D[1]=inf;
t[0].U[0]=t[0].U[1]=-inf;
build(rt,1,n,0);
for(int i=1;i<=n;i++){
query_min(rt,a[i],0,i);
query_max(rt,a[i],0,i);
}
printf("%.2f %.2f\n",sqrt(mn),sqrt(mx));
return 0;
}
矩形查询+二进制分组修改
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n;
struct point{
int x[2];
int val;
point make_point(int ax,int ay,int v){
point tmp;
tmp.x[0]=ax;tmp.x[1]=ay;tmp.val=v;
return tmp;
}
}a[MAXN];
struct node{
point x;
int sum;
int ls,rs;
int D[2],U[2];
}t[MAXN];
int rt[25],tot,bn[MAXN],dcnt,cnt;
int ans;
const int inf=1e9;
int get_new(){
if(dcnt) return bn[dcnt--];
else return ++tot;
}
void del(int &k){
t[k].ls=t[k].rs=t[k].sum=0;
bn[++dcnt]=k;
k=0;
}
int kk;
bool cmp(point aa,point bb){
return aa.x[kk]<bb.x[kk];
}
void init(int &k){
if(!k) return;
a[++cnt]=t[k].x;
init(t[k].ls);
init(t[k].rs);
del(k);
}
void pushup(int k){
for(int i=0;i<=1;i++){
t[k].D[i]=min(t[k].x.x[i],min(t[t[k].ls].D[i],t[t[k].rs].D[i]));
t[k].U[i]=max(t[k].x.x[i],max(t[t[k].ls].U[i],t[t[k].rs].U[i]));
}
t[k].sum=t[t[k].ls].sum+t[t[k].rs].sum+t[k].x.val;
}
void build(int &k,int l,int r,int dm){
if(l>r) return;
k=get_new();
int mid=(l+r)>>1;
kk=dm;
nth_element(a+l,a+mid,a+r+1,cmp);
t[k].x=a[mid];
build(t[k].ls,l,mid-1,dm^1);
build(t[k].rs,mid+1,r,dm^1);
pushup(k);
}
bool check(int x[],int y[]){
int res=0;
for(int i=0;i<=1;i++){
if(x[i]<=y[i]) res++;
}
if(res==2) return true;
else return false;
}
void query(int k,point d,point u,int dm){
if(!k) return;
if(!check(t[k].D,u.x) || !check(d.x,t[k].U)) return;
if(check(d.x,t[k].D) && check(t[k].U,u.x)){
ans+=t[k].sum;
return;
}
if(check(d.x,t[k].x.x) && check(t[k].x.x,u.x)){
ans+=t[k].x.val;
}
query(t[k].ls,d,u,dm^1);
query(t[k].rs,d,u,dm^1);
}
int main(){
n=read();
int op,ax,ay,bx,by,v;
t[0].D[0]=t[0].D[1]=inf;
t[0].U[0]=t[0].U[1]=0;
while(1){
op=read();
if(op==1){
ax=read();ay=read();v=read();
ax^=ans;ay^=ans;v^=ans;
point tmp=tmp.make_point(ax,ay,v);
t[++tot].x=tmp;
cnt=0;
a[++cnt]=tmp;
for(int i=0;;i++){
if(rt[i]){
init(rt[i]);
}else{
build(rt[i],1,cnt,0);
break;
}
}
}else if(op==2){
ax=read();ay=read();
bx=read();by=read();
ax^=ans;ay^=ans;bx^=ans;by^=ans;
point aa={min(ax,bx),min(ay,by)};
point bb={max(ax,bx),max(ay,by)};
ans=0;
for(int i=0;i<=20;i++){
if(rt[i]) query(rt[i],aa,bb,0);
}
printf("%d\n",ans);
}else if(op==3){
break;
}
}
return 0;
}
虚树
void build(){
sort(q+1,q+1+k,cmp);
top=0;
st[++top]=q[1];
for(int i=2;i<=k;i++){
int lca=LCA(st[top],q[i]);
while(dep[lca]<dep[st[top-1]]){
add(st[top-1],st[top]);
top--;
}
if(lca!=st[top]){
add(lca,st[top]);
if(lca!=st[top-1]) st[top]=lca;
else top--;
}
st[++top]=q[i];
}
while(--top){
add(st[top],st[top+1]);
}
}
LCT
#include<bits/stdc++.h>
#define MAXN 100005
#define ls ch[x][0]
#define rs ch[x][1]
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int fa[MAXN],ch[MAXN][3],val[MAXN],sum[MAXN],rv[MAXN];
stack<int> st;
bool notrt(int x){
return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
}
void pushup(int x){
sum[x]=sum[ls]^sum[rs]^val[x];
}
void makerv(int x){
rv[x]^=1;
swap(ls,rs);
}
void pushdown(int x){
if(rv[x]){
if(ls) makerv(ls);
if(rs) makerv(rs);
rv[x]=0;
}
}
void pushdn(int x){
while(!st.empty()) st.pop();
st.push(x);
while(notrt(x)){
x=fa[x];
st.push(x);
}
while(!st.empty()){
pushdown(st.top());
st.pop();
}
}
void rotate(int x){
int y=fa[x],z=fa[y];
int k=(ch[y][1]==x);
int w=ch[x][k^1];
if(notrt(y)) ch[z][ch[z][1]==y]=x;
fa[x]=z;
fa[fa[ch[ch[x][k^1]=y][k]=w]=y]=x;
pushup(y);
pushup(x);
}
void splay(int x){
pushdn(x);
while(notrt(x)){
int y=fa[x],z=fa[y];
if(notrt(y)){
if((ch[y][1]==x) == (ch[z][1]==y)) rotate(y);
else rotate(x);
}
rotate(x);
}
}
void access(int x){
for(int y=0;x;y=x,x=fa[x]){
splay(x);
ch[x][1]=y;
pushup(x);
}
}
void makeroot(int x){
access(x);
splay(x);
makerv(x);
}
int findroot(int x){
access(x);
splay(x);
while(ls){
pushdown(x);
x=ls;
}
splay(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;
pushup(y);
}
void cut(int x,int y){
split(x,y);
if(ch[y][0]!=x || ch[y][1]) return;
ch[y][0]=fa[x]=0;
pushup(y);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
val[i]=read();
}
int op,x,y;
while(m--){
op=read();
x=read();y=read();
if(op==0){
split(x,y);
printf("%d\n",sum[y]);
}else if(op==1){
link(x,y);
}else if(op==2){
cut(x,y);
}else{
splay(x);
val[x]=y;
pushup(x);
}
}
return 0;
}
线段树分治
#include<bits/stdc++.h>
#define MAXN 400005
#define ls k<<1
#define rs k<<1|1
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,k;
struct enode{
int u,v;
}E[MAXN];
int fa[MAXN],sz[MAXN];
struct node{
int l,r;
int sum;
vector<enode> v;
}t[MAXN<<2];
int w[MAXN];
int st[MAXN],top;
int find(int x){
if(x==fa[x]) return fa[x];
return find(fa[x]);
}
void merge(int x,int y){
x=find(x);y=find(y);
if(x!=y){
if(sz[x]>sz[y]) swap(x,y);
fa[x]=y;
sz[y]+=sz[x];
st[++top]=x;
}
}
void del(int x){
sz[fa[x]]-=sz[x];
fa[x]=x;
}
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
if(l==r) return;
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
}
void update(int k,int l,int r,enode x){
if(t[k].l>=l && t[k].r<=r){
t[k].v.push_back(x);
return;
}
int mid=(t[k].l+t[k].r)>>1;
if(mid>=l) update(ls,l,r,x);
if(mid<r) update(rs,l,r,x);
}
void query(int k){
int tmp=top;
bool flag=true;
for(auto x:t[k].v){
int u=find(x.u);
int v=find(x.v);
if(u==v){
for(int i=t[k].l;i<=t[k].r;i++) puts("No");
flag=false;
break;
}
merge(x.u,x.v+n);
merge(x.v,x.u+n);
}
if(flag){
if(t[k].l==t[k].r){
puts("Yes");
while(top>tmp){
del(st[top--]);
}
return;
}
query(ls);
query(rs);
}
while(top>tmp){
del(st[top--]);
}
}
int main(){
n=read();m=read();k=read();
build(1,1,k);
for(int i=1;i<=2*n;i++){
fa[i]=i;
sz[i]=1;
}
int u,v,l,r;
for(int i=1;i<=m;i++){
u=read();v=read();
l=read()+1;r=read();
E[i].u=u;
E[i].v=v;
enode t={u,v};
update(1,l,r,t);
}
query(1);
return 0;
}
线段树合并
#include<bits/stdc++.h>
#define MAXN 100005
#define mod 998244353
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n,m;
vector<int> edge[MAXN];
int fa[MAXN][25],dep[MAXN];
int rt[MAXN];
int ans[MAXN];
const int N=100000;
void dfs0(int x,int f){
dep[x]=dep[f]+1;
fa[x][0]=f;
for(auto y:edge[x]){
if(y==f) continue;
dfs0(y,x);
}
}
void init(){
for(int j=1;j<=21;j++){
for(int i=1;i<=n;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int LCA(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int step=dep[a]-dep[b];
for(int i=0;i<=20;i++){
if(step&(1<<i)) a=fa[a][i];
}
if(a==b) return a;
for(int i=20;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
struct segment_tree{
struct node{
int lc,rc;
int val,ty;
}t[MAXN*80];
int tot;
#define ls t[k].lc
#define rs t[k].rc
void pushup(int k){
if(t[ls].val>=t[rs].val){
t[k].val=t[ls].val;
t[k].ty=t[ls].ty;
}else{
t[k].val=t[rs].val;
t[k].ty=t[rs].ty;
}
if(!t[k].val) t[k].ty=0;
}
void update(int &k,int l,int r,int p,int v){
if(!k) k=++tot;
if(l==r){
t[k].val+=v;
t[k].ty=l;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(ls,l,mid,p,v);
else update(rs,mid+1,r,p,v);
pushup(k);
}
int merge(int x,int y,int l,int r){
if(!x) return y;
if(!y) return x;
if(l==r){
t[x].val+=t[y].val;
t[x].ty=l;
return x;
}
int mid=(l+r)>>1;
t[x].lc=merge(t[x].lc,t[y].lc,l,mid);
t[x].rc=merge(t[x].rc,t[y].rc,mid+1,r);
pushup(x);
return x;
}
}ST;
void dfs(int x,int f){
for(auto y:edge[x]){
if(y==f) continue;
dfs(y,x);
rt[x]=ST.merge(rt[x],rt[y],1,N);
}
ans[x]=ST.t[rt[x]].ty;
}
bool M2;
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int Time=clock();
n=read();m=read();
int u,v;
for(int i=1;i<n;i++){
u=read();v=read();
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs0(1,0);
init();
int w;
for(int i=1;i<=m;i++){
u=read();v=read();w=read();
int lca=LCA(u,v);
ST.update(rt[u],1,N,w,1);
ST.update(rt[v],1,N,w,1);
ST.update(rt[lca],1,N,w,-1);
if(fa[lca][0]) ST.update(rt[fa[lca][0]],1,N,w,-1);
}
dfs(1,0);
for(int i=1;i<=n;i++){
printf("%d\n",ans[i]);
}
look_memory;
look_time;
return 0;
}
线段树分裂
#include<bits/stdc++.h>
#define MAXN 200005
#define mod 998244353
#define ls t[k].lc
#define rs t[k].rc
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n,m;
struct node{
int lc,rc;
long long val;
}t[MAXN*40];
int rt[MAXN],tot,rcnt;
int bn[MAXN*5],dcnt;
int get_new(){
if(dcnt) return bn[dcnt--];
else return ++tot;
}
void del(int k){
ls=rs=t[k].val=0;
bn[++dcnt]=k;
}
void pushup(int k){
t[k].val=t[ls].val+t[rs].val;
}
void update(int &k,int l,int r,int p,int v){
if(!k) k=get_new();
if(l==r){
t[k].val+=v;
return;
}
int mid=(l+r)>>1;
if(mid>=p) update(ls,l,mid,p,v);
else update(rs,mid+1,r,p,v);
pushup(k);
}
void split(int k,int &x,int &y,int l,int r,int L,int R){
if(!k) return;
if(l>=L && r<=R){
y=x;
x=0;
return;
}
y=get_new();
int mid=(l+r)>>1;
if(mid>=L) split(ls,t[x].lc,t[y].lc,l,mid,L,R);
if(mid<R) split(rs,t[x].rc,t[y].rc,mid+1,r,L,R);
pushup(x);
pushup(y);
}
void merge(int &x,int y){
if(!x || !y){
x=x+y;
return;
}
t[x].val+=t[y].val;
merge(t[x].lc,t[y].lc);
merge(t[x].rc,t[y].rc);
del(y);
}
long long query(int k,int l,int r,int L,int R){
if(l>=L && r<=R){
return t[k].val;
}
int mid=(l+r)>>1;
long long res=0;
if(mid>=L) res+=query(ls,l,mid,L,R);
if(mid<R) res+=query(rs,mid+1,r,L,R);
return res;
}
int ask_kth(int k,int l,int r,int num){
if(l==r) return l;
int mid=(l+r)>>1;
if(t[ls].val>=num) return ask_kth(ls,l,mid,num);
else return ask_kth(rs,mid+1,r,num-t[ls].val);
}
bool M2;
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int Time=clock();
n=read();m=read();
rcnt=1;
int x;
for(int i=1;i<=n;i++){
x=read();
update(rt[1],1,n,i,x);
}
int op,id,y;
while(m--){
op=read();
if(op==0){
id=read();
x=read();y=read();
split(rt[id],rt[id],rt[++rcnt],1,n,x,y);
}else if(op==1){
x=read();y=read();
merge(rt[x],rt[y]);
}else if(op==2){
id=read();
x=read();y=read();
update(rt[id],1,n,y,x);
}else if(op==3){
id=read();
x=read();y=read();
printf("%lld\n",query(rt[id],1,n,x,y));
}else{
id=read();x=read();
if(t[rt[id]].val<x){
puts("-1");
continue;
}
printf("%d\n",ask_kth(rt[id],1,n,x));
}
}
look_memory;
look_time;
return 0;
}
离线算法
整体二分
#include<bits/stdc++.h>
#define MAXN 600005
#define inf 1000000000
using namespace std;
inline long long read(){
long long x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,k;
long long c[MAXN];
vector<int> edge[MAXN];
struct node1{
int l,r;
long long val;
}a[MAXN];
struct node2{
long long nd;
int id;
}p[MAXN],tmp[MAXN];
int ans[MAXN];
int lowbit(int x){
return x&(-x);
}
void update(int x,long long v){
while(x<=2*m){
c[x]+=v;
x+=lowbit(x);
}
}
long long query(int x){
long long res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
}
void whole_bny(int l,int r,int ql,int qr){
if(qr<ql) return;
if(l==r){
for(int i=ql;i<=qr;i++){
ans[p[i].id]=l;
}
return;
}
int mid=(l+r)>>1;
for(int i=l;i<=mid;i++){
update(a[i].l,a[i].val);
update(a[i].r+1,-a[i].val);
}
int cnt1=0,cnt2=n;
for(int i=ql;i<=qr;i++){
long long sum=0;
for(auto y:edge[p[i].id]){
sum+=query(y)+query(y+m);
if(sum>p[i].nd) break;
}
if(sum>=p[i].nd){
tmp[++cnt1]=p[i];
}else{
tmp[++cnt2]=p[i];
tmp[cnt2].nd-=sum;
}
}
for(int i=l;i<=mid;i++){
update(a[i].l,-a[i].val);
update(a[i].r+1,a[i].val);
}
for(int i=1;i<=cnt1;i++){
p[ql+i-1]=tmp[i];
}
for(int i=n+1;i<=cnt2;i++){
p[ql+cnt1+i-n-1]=tmp[i];
}
whole_bny(l,mid,ql,ql+cnt1-1);
whole_bny(mid+1,r,ql+cnt1,qr);
}
int main(){
n=read();m=read();
int o;
for(int i=1;i<=m;i++){
o=read();
edge[o].push_back(i);
}
for(int i=1;i<=n;i++){
p[i].nd=read();
p[i].id=i;
}
k=read();
for(int i=1;i<=k;i++){
a[i].l=read();
a[i].r=read();
a[i].val=read();
if(a[i].r<a[i].l) a[i].r+=m;
}
whole_bny(1,k+1,1,n);
for(int i=1;i<=n;i++){
if(ans[i]>k){
puts("NIE");
}else{
printf("%d\n",ans[i]);
}
}
return 0;
}
CDQ分治
#include<bits/stdc++.h>
#define MAXN 100005
#define MAXK 200005
using namespace std;
inline int read(){
int x=0;
char c=0;
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,nn,k;
struct node{
int x,y,z;
int res,cnt;
}b[MAXN],a[MAXN],t[MAXN];
int c[MAXK];
int ans[MAXK];
bool cmp1(node aa,node bb){
if(aa.x==bb.x){
if(aa.y==bb.y) return aa.z<bb.z;
return aa.y<bb.y;
}
return aa.x<bb.x;
}
bool cmp2(node aa,node bb){
if(aa.y==bb.y) return aa.z<bb.z;
return aa.y<bb.y;
}
int lowbit(int x){
return x&(-x);
}
void add(int x,int v){
while(x<=k){
c[x]+=v;
x+=lowbit(x);
}
return;
}
int query(int x){
int res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
}
void CDQ(int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
CDQ(l,mid);
CDQ(mid+1,r);
int i=l,j=mid+1;
for(;j<=r;j++){
while(i<=mid && a[i].y<=a[j].y){
add(a[i].z,a[i].cnt);
i++;
}
a[j].res+=query(a[j].z);
}
i=l,j=mid+1;
for(;j<=r;j++){
while(i<=mid && a[i].y<=a[j].y){
add(a[i].z,-a[i].cnt);
i++;
}
}
inplace_merge(a+l,a+mid+1,a+r+1,cmp2);
}
int main(){
n=read();k=read();
for(int i=1;i<=n;i++){
b[i].x=read();
b[i].y=read();
b[i].z=read();
}
sort(b+1,b+1+n,cmp1);
int tmp=0;
for(int i=1;i<=n;i++){
tmp++;
if(b[i].x!=b[i+1].x || b[i].y!=b[i+1].y || b[i].z!=b[i+1].z){
a[++nn]=b[i];
a[nn].cnt=tmp;
tmp=0;
}
}
swap(n,nn);
CDQ(1,n);
for(int i=1;i<=n;i++){
ans[a[i].res+a[i].cnt-1]+=a[i].cnt;
}
for(int i=0;i<nn;i++){
printf("%d\n",ans[i]);
}
return 0;
}
莫队
#include<bits/stdc++.h>
#define MAXN 50005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int c[MAXN],cnt[MAXN];
struct node{
int id;
int l,r;
}q[MAXN];
int pos[MAXN],len;
struct node2{
long long p,q;
}ans[MAXN];
long long sum;//ƽ·½ºÍ
bool cmp(node aa,node bb){
if(pos[aa.l]==pos[bb.l]) return aa.r<bb.r;
return aa.l<bb.l;
}
long long gcd(long long aa,long long bb){
if(bb==0) return aa;
return gcd(bb,aa%bb);
}
void add(int x){
sum+=cnt[x];
cnt[x]++;
}
void del(int x){
cnt[x]--;
sum-=cnt[x];
}
void solve(){
for(int i=1,l=1,r=0;i<=m;i++){
while(l>q[i].l) add(c[--l]);
while(r<q[i].r) add(c[++r]);
while(l<q[i].l) del(c[l++]);
while(r>q[i].r) del(c[r--]);
if(q[i].l==q[i].r){
ans[q[i].id].p=0;
ans[q[i].id].q=1;
continue;
}
ans[q[i].id].p=sum;
ans[q[i].id].q=(long long)(r-l+1)*(r-l)/2;
}
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
c[i]=read();
}
for(int i=1;i<=m;i++){
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
len=sqrt(n);
for(int i=1;i<=n;i++){
pos[i]=(i-1)/len+1;
}
sort(q+1,q+1+m,cmp);
solve();
for(int i=1;i<=m;i++){
int g=gcd(ans[i].p,ans[i].q);
if(g){
ans[i].p/=g;
ans[i].q/=g;
}
printf("%d/%d\n",ans[i].p,ans[i].q);
}
return 0;
}
回滚莫队
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline long long read(){
long long x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int a[MAXN];
struct node{
int l,r;
int id;
}q[MAXN];
int pos[MAXN],len;
int lsh[MAXN],nn;
int bg[MAXN],ed[MAXN],ed2[MAXN];
int res1,res2;
int ans[MAXN];
bool cmp(node aa,node bb){
if(pos[aa.l]==pos[bb.l]) return aa.r<bb.r;
return aa.l<bb.l;
}
void solve(){
int block=0,nowb=0,l=0,r=0;
for(int i=1;i<=m;i++){
if(pos[q[i].l]==pos[q[i].r]){
for(int j=q[i].l;j<=q[i].r;j++){
bg[a[j]]=0;
}
res1=0;
for(int j=q[i].l;j<=q[i].r;j++){
if(!bg[a[j]]) bg[a[j]]=j;
res1=max(res1,j-bg[a[j]]);
}
ans[q[i].id]=res1;
for(int j=q[i].l;j<=q[i].r;j++){
bg[a[j]]=0;
}
res1=0;
continue;
}
nowb=pos[q[i].l];
if(block!=nowb){
res1=0;
for(int j=l;j<=r;j++){
bg[a[j]]=ed[a[j]]=0;
}
l=min(n,nowb*len);
r=l-1;
block=nowb;
}
while(r<q[i].r){
r++;
if(!bg[a[r]]) bg[a[r]]=r;
ed[a[r]]=r;
res1=max(res1,r-bg[a[r]]);
}
int t=l,res2=0;
while(t>q[i].l){
t--;
if(!ed2[a[t]]) ed2[a[t]]=t;
res2=max(res2,max(ed[a[t]],ed2[a[t]])-t);
}
while(t<l){
ed2[a[t]]=0;
t++;
}
ans[q[i].id]=max(res1,res2);
}
}
int main(){
//freopen("P5906.in","r",stdin);
//freopen("P5906.out","w",stdout);
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
lsh[i]=a[i];
}
sort(lsh+1,lsh+1+n);
nn=unique(lsh+1,lsh+1+n)-lsh-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(lsh+1,lsh+1+nn,a[i])-lsh;
}
m=read();
for(int i=1;i<=m;i++){
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
len=sqrt(n);
for(int i=1;i<=n;i++){
pos[i]=(i-1)/len+1;
}
sort(q+1,q+1+m,cmp);
solve();
for(int i=1;i<=m;i++){
printf("%d\n",ans[i]);
}
return 0;
}
带修莫队
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
inline long long read(){
long long x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
int a[MAXN];
int cntq,cntp;
struct node{
int l,r,t;
int id;
}q[MAXN];
struct node1{
int x,y;
}p[MAXN];
int cnt[1000005];
int pos[MAXN],len;
int ans[MAXN],res;
bool cmp(node aa,node bb){
if(pos[aa.l]==pos[bb.l]){
if(pos[aa.r]==pos[bb.r]) return aa.t<bb.t;
return aa.r<bb.r;
}
return aa.l<bb.l;
}
void add(int x){
if(!cnt[x]) res++;
cnt[x]++;
}
void del(int x){
cnt[x]--;
if(!cnt[x]) res--;
}
void upd(int id,int x){
if(q[id].l<=p[x].x && q[id].r>=p[x].x){
del(a[p[x].x]);
add(p[x].y);
}
swap(a[p[x].x],p[x].y);
}
void solve(){
int l=1,r=0,t=0;
for(int i=1;i<=cntq;i++){
while(l>q[i].l) add(a[--l]);
while(l<q[i].l) del(a[l++]);
while(r>q[i].r) del(a[r--]);
while(r<q[i].r) add(a[++r]);
while(t<q[i].t) upd(i,++t);
while(t>q[i].t) upd(i,t--);
ans[q[i].id]=res;
}
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
char op[5];
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='Q'){
cntq++;
q[cntq].l=read();q[cntq].r=read();
q[cntq].t=cntp;q[cntq].id=cntq;
}else{
cntp++;
p[cntp].x=read();p[cntp].y=read();
}
}
len=pow(n,0.666);
for(int i=1;i<=n;i++){
pos[i]=(i-1)/len+1;
}
sort(q+1,q+1+cntq,cmp);
solve();
for(int i=1;i<=cntq;i++){
printf("%d\n",ans[i]);
}
return 0;
}
- 二离莫队
图论
最短路 SPFA dijkstra
int n,m,s;
struct node{
int to,val;
bool operator < (node tmp) const{
return tmp.val<val;
}
};
vector<node> edge[MAXN];
priority_queue<node> q;
bool vis[MAXN];
int dis[MAXN];
void dijkstra(){
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push((node){s,0});
while(!q.empty()){
node tmp=q.top();
q.pop();
int u=tmp.to;
if(vis[u]) continue;
vis[u]=true;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i].to;
int w=edge[u][i].val;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push((node){v,dis[v]});
}
}
}
}
int n,m,s;
struct node{
int to,val;
};
vector<node> edge[MAXN];
queue<int> q;
bool vis[MAXN];
int dis[MAXN];
void SPFA(){
for(int i=1;i<=n;i++){
dis[i]=inf;
}
dis[s]=0;
q.push(s);
vis[s]=true;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i].to;
int w=edge[u][i].val;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
q.push(v);
vis[v]=true;
}
}
}
}
}
最小生成树
拓扑排序
差分约束
tarjan
缩点
int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int belong[MAXN],bcnt;
stack<int> st;
bool inst[MAXN];
void tarjan(int x){
dfn[x]=low[x]=++tot;
st.push(x);
inst[x]=true;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}else if(inst[y]){
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x]){
int k;
bcnt++;
do{
k=st.top();
st.pop();
belong[k]=bcnt;
inst[k]=false;
}while(k!=x);
}
}
割点
#include<bits/stdc++.h>
#define MAXN 20005
using namespace std;
inline int read(){
int x=0;
char c=0;
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int buc[MAXN],cnt;
int root;
void tarjan(int x){
dfn[x]=low[x]=++tot;
int son=0;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(!dfn[y]){
son++;
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x] && x!=root){
if(!buc[x]){
++cnt;
buc[x]=true;
}
}
}else{
low[x]=min(low[x],dfn[y]);
}
}
if(x==root && son>1){
++cnt;
buc[x]=true;
}
return;
}
int main(){
n=read();m=read();
int u,v;
for(int i=1;i<=m;i++){
u=read();v=read();
edge[u].push_back(v);
edge[v].push_back(u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
root=i;
tarjan(i);
}
}
printf("%d\n",cnt);
for(int i=1;i<=n;i++){
if(buc[i]) printf("%d ",i);
}
return 0;
}
割边
点双
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline int read(){
int x=0;
char c=0;
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
stack<int> st;
int bcc;
vector<int> ans[MAXN];
void tarjan(int x,int f){
dfn[x]=low[x]=++tot;
st.push(x);
int son=0;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(!dfn[y]){
son++;
tarjan(y,x);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]){
int k;
bcc++;
do{
k=st.top();
st.pop();
ans[bcc].push_back(k);
}while(k!=y);
ans[bcc].push_back(x);
}
}else{
low[x]=min(low[x],dfn[y]);
}
}
if(f==0 && son==0) ans[++bcc].push_back(x);
return;
}
int main(){
n=read();m=read();
int u,v;
for(int i=1;i<=m;i++){
u=read();v=read();
edge[u].push_back(v);
edge[v].push_back(u);
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,0);
}
printf("%d\n",bcc);
for(int i=1;i<=bcc;i++){
printf("%d ",ans[i].size());
for(int j=0;j<ans[i].size();j++){
printf("%d ",ans[i][j]);
}
puts("");
}
return 0;
}
边双
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline int read(){
int x=0;
char c=0;
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
struct node{
int to,id;
};
vector<node> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
vector<int> ans[MAXN];
int belong[MAXN],bcnt;
stack<int> st;
void tarjan(int x,int fe){
dfn[x]=low[x]=++tot;
st.push(x);
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i].to;
int e=edge[x][i].id;
if(e==(fe^1)) continue;
if(!dfn[y]){
tarjan(y,e);
low[x]=min(low[x],low[y]);
}else{
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x]){
bcnt++;
int k;
do{
k=st.top();
st.pop();
belong[k]=bcnt;
ans[bcnt].push_back(k);
}while(k!=x);
}
}
int main(){
n=read();m=read();
int u,v;
for(int i=1;i<=m;i++){
u=read();v=read();
edge[u].push_back((node){v,i<<1});
edge[v].push_back((node){u,i<<1|1});
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,0);
}
printf("%d\n",bcnt);
for(int i=1;i<=bcnt;i++){
printf("%d ",ans[i].size());
for(int j=0;j<ans[i].size();j++){
printf("%d ",ans[i][j]);
}
puts("");
}
return 0;
}
二分图最大匹配
#include<bits/stdc++.h>
#define MAXN 1005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,e;
vector<int> edge[MAXN];
int ans;
bool vis[MAXN<<1];
int f[MAXN<<1];
bool sp(int x){
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(!vis[y]){
vis[y]=true;
if(!f[y] || sp(f[y])){
f[y]=x;
return true;
}
}
}
return false;
}
void match(){
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(sp(i)){
ans++;
}
}
}
int main(){
//freopen("","r",stdin);
//freopen("","w",stdout);
n=read();m=read();e=read();
int u,v;
for(int i=1;i<=e;i++){
u=read();v=read();
edge[u].push_back(v);
}
match();
printf("%d",ans);
return 0;
}
2-SAT
#include<bits/stdc++.h>
#define MAXN 2000005
#define mod 1000000007
using namespace std;
inline int read(){
int x=0;
char c=0;
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int belong[MAXN],bcnt;
stack<int> st;
bool inst[MAXN];
void tarjan(int x){
dfn[x]=low[x]=++tot;
st.push(x);
inst[x]=true;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}else if(inst[y]){
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x]){
bcnt++;
int k;
do{
k=st.top();
st.pop();
inst[k]=false;
belong[k]=bcnt;
}while(k!=x);
}
}
int main(){
n=read();m=read();
int u,v,a,b;
for(int i=1;i<=m;i++){
u=read();a=read();
v=read();b=read();
u--;v--;
edge[(u<<1)+!a].push_back((v<<1)+b);
edge[(v<<1)+!b].push_back((u<<1)+a);
}
for(int i=0;i<(n<<1);i++){
if(!dfn[i]) tarjan(i);
}
for(int i=0;i<(n<<1);i+=2){
if(belong[i]==belong[i+1]){
puts("IMPOSSIBLE");
return 0;
}
}
puts("POSSIBLE");
for(int i=0;i<(n<<1);i+=2){
if(belong[i]<belong[i+1]){
printf("0 ");
}else{
printf("1 ");
}
}
return 0;
}
圆方树
仙人掌建树
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,q;
int sum[MAXN<<1];
int cnt;
struct round_sqare_tree{
struct node{
int to,val;
};
vector<node> edge[MAXN<<1];
int fa[MAXN<<1][25],dep[MAXN<<1],dis[MAXN<<1];
void add(int u,int v,int w){
edge[u].push_back((node){v,w});
}
void dfs(int x,int ff){
fa[x][0]=ff;
dep[x]=dep[ff]+1;
for(auto tmp:edge[x]){
int y=tmp.to;
int w=tmp.val;
if(y==ff) continue;
dis[y]=dis[x]+w;
dfs(y,x);
}
}
void init(){
for(int j=1;j<=21;j++){
for(int i=1;i<=cnt;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int get_dis(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int a=x,b=y;
int step=dep[a]-dep[b];
for(int i=0;i<=20;i++){
if(step&(1<<i)) a=fa[a][i];
}
if(a==b){
return dis[x]-dis[y];
}
for(int i=20;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
int lca=fa[a][0];
if(lca>n){
return dis[x]+dis[y]-dis[a]-dis[b]+min(abs(sum[a]-sum[b]),sum[lca]-abs(sum[a]-sum[b]));
}else{
return dis[x]+dis[y]-2*dis[lca];
}
}
}RST;
struct cactus{
struct node{
int to,val;
};
vector<node> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
int fa[MAXN],vl[MAXN];
void add(int u,int v,int w){
edge[u].push_back((node){v,w});
}
void solve(int t,int s,int w){
cnt++;
int p=s,sm=w;
while(p!=fa[t]){
sum[p]=sm;
sm+=vl[p];
p=fa[p];
}
sum[cnt]=sum[t];
sum[t]=0;
p=s;
while(p!=fa[t]){
int mn=min(sum[p],sum[cnt]-sum[p]);
RST.add(p,cnt,mn);
RST.add(cnt,p,mn);
p=fa[p];
}
}
void tarjan(int x,int ff){
dfn[x]=low[x]=++tot;
for(auto tmp:edge[x]){
int y=tmp.to;
int w=tmp.val;
if(y==ff) continue;
if(!dfn[y]){
fa[y]=x;
vl[y]=w;
tarjan(y,x);
low[x]=min(low[x],low[y]);
}else{
low[x]=min(low[x],dfn[y]);
}
if(low[y]<=dfn[x]) continue;//是割点,则子树内有点双
RST.add(x,y,w);
RST.add(y,x,w);
}
for(auto tmp:edge[x]){
int y=tmp.to;
if(fa[y]!=x && dfn[y]>dfn[x]) solve(x,y,tmp.val);
}
}
}CC;
int main(){
n=read();m=read();q=read();
int u,v,w;
for(int i=1;i<=m;i++){
u=read();v=read();w=read();
CC.add(u,v,w);
CC.add(v,u,w);
}
cnt=n;
CC.tarjan(1,0);
RST.dfs(1,0);
RST.init();
while(q--){
u=read();v=read();
int ans=RST.get_dis(u,v);
printf("%d\n",ans);
}
return 0;
}
点双建树
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,q;
int w[MAXN<<1];
int cnt;
struct round_sqare_tree{
vector<int> edge[MAXN<<1];
int fa[MAXN<<1][25],dep[MAXN<<1],dis[MAXN<<1];
void add(int u,int v){
edge[u].push_back(v);
}
void dfs(int x,int ff){
fa[x][0]=ff;
dep[x]=dep[ff]+1;
dis[x]=dis[ff]+w[x];
for(auto y:edge[x]){
if(y==ff) continue;
dfs(y,x);
}
}
void init(){
for(int j=1;j<=21;j++){
for(int i=1;i<=cnt;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int LCA(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int step=dep[a]-dep[b];
for(int i=0;i<=20;i++){
if(step&(1<<i)) a=fa[a][i];
}
if(a==b) return a;
for(int i=20;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
int get_dis(int x,int y){
int lca=LCA(x,y);
return dis[x]+dis[y]-dis[lca]-dis[fa[lca][0]];
}
}RST;
struct cactus{
vector<int> edge[MAXN];
int dfn[MAXN],low[MAXN],tot;
stack<int> st;
void add(int u,int v){
edge[u].push_back(v);
}
void solve(int x,int y){
cnt++;
int k;
do{
k=st.top();
st.pop();
RST.add(cnt,k);
RST.add(k,cnt);
}while(k!=y);
RST.add(cnt,x);
RST.add(x,cnt);
}
void tarjan(int x,int ff){
dfn[x]=low[x]=++tot;
st.push(x);
for(auto y:edge[x]){
if(!dfn[y]){
tarjan(y,x);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x]) solve(x,y);
}else{
low[x]=min(low[x],dfn[y]);
}
}
}
}CC;
int main(){
n=read();m=read();
int u,v;
for(int i=1;i<=m;i++){
u=read();v=read();
CC.add(u,v);
CC.add(v,u);
}
for(int i=1;i<=n;i++) w[i]=1;
cnt=n;
CC.tarjan(1,0);
RST.dfs(1,0);
RST.init();
q=read();
while(q--){
u=read();v=read();
int ans=RST.get_dis(u,v);
printf("%d\n",ans);
}
return 0;
}
网络流
最大流
#include<bits/stdc++.h>
#define MAXN 205
#define MAXM 5005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m,s,t;
struct node{
int to,val,nxt;
}E[MAXM<<1];
int cnt=1;
int head[MAXN],now[MAXN];
long long ans;
int dis[MAXN];
queue<int> q;
const int inf=0x3f3f3f3f3f3f3f3f;
void add(int u,int v,int w){
cnt++;
E[cnt].to=v;
E[cnt].val=w;
E[cnt].nxt=head[u];
head[u]=cnt;
}
bool bfs(){
memset(dis,0x3f,sizeof(dis));
while(!q.empty()) q.pop();
q.push(s);
dis[s]=0;
now[s]=head[s];
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=E[i].nxt){
int y=E[i].to;
int w=E[i].val;
if(w>0 && dis[y]==inf){
q.push(y);
now[y]=head[y];
dis[y]=dis[x]+1;
if(y==t) return true;
}
}
}
return false;
}
long long dfs(int x,int mn){
if(x==t) return mn;
long long res=0;
for(int i=now[x];i && mn;i=E[i].nxt){
int y=E[i].to;
int w=E[i].val;
now[x]=i;
if(w>0 && dis[y]==dis[x]+1){
long long t=dfs(y,min(mn,w));
if(!t) dis[y]=inf;
E[i].val-=t;
E[i^1].val+=t;
res+=t;
mn-=t;
}
}
return res;
}
void Dinic(){
while(bfs()){
ans+=dfs(s,inf);
}
}
int main(){
//freopen("","r",stdin);
//freopen("","w",stdout);
n=read();m=read();
s=read();t=read();
int u,v,w;
for(int i=1;i<=m;i++){
u=read();v=read();w=read();
add(u,v,w);
add(v,u,0);
}
Dinic();
printf("%lld",ans);
return 0;
}
费用流
#include<bits/stdc++.h>
#define MAXN 5005
#define MAXM 50005
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n,m;
int s,t;
int head[MAXN],to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1],cst[MAXM<<1],cnt=1;
int dis[MAXN],f[MAXN],pre[MAXN];
bool vis[MAXN];
queue<int> q;
int ans,ansc;
const int inf=1e9;
bool M2;
void add(int u,int v,int w,int c){
cnt++;
to[cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
val[cnt]=w;
cst[cnt]=c;
}
bool SPFA(){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
q.push(s);
vis[s]=1;
dis[s]=0;
f[s]=inf;
f[t]=0;
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
int w=val[i];
int c=cst[i];
if(!w || dis[y]<=dis[x]+c) continue;
dis[y]=dis[x]+c;
f[y]=min(f[x],w);
pre[y]=i;
if(!vis[y]){
q.push(y);
vis[y]=1;
}
}
}
if(f[t]) return true;
else return false;
}
void update(){
ans+=f[t];
for(int x=t;x!=s;x=to[pre[x]^1]){
val[pre[x]]-=f[t];
val[pre[x]^1]+=f[t];
ansc+=f[t]*cst[pre[x]];
}
}
void EK(){
while(SPFA()){
update();
}
}
int main(){
// freopen("","r",stdin);
// freopen("","w",stdout);
int Time=clock();
n=read();m=read();
s=read();t=read();
int u,v,w,c;
for(int i=1;i<=m;i++){
u=read();v=read();w=read();c=read();
add(u,v,w,c);
add(v,u,0,-c);
}
EK();
printf("%d %d",ans,ansc);
return 0;
}
树论
LCA
int n,m,s;
vector<int> edge[MAXN];
int fa[MAXN][25],dep[MAXN];
void dfs(int x,int f){
fa[x][0]=f;
dep[x]=dep[f]+1;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(y==f) continue;
dfs(y,x);
}
}
void init(){
for(int j=1;j<=21;j++){
for(int i=1;i<=n;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int LCA(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int step=dep[a]-dep[b];
for(int i=0;i<=20;i++){
if(step&(1<<i)){
a=fa[a][i];
}
}
if(a==b) return a;
for(int i=20;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
树的重心
int n;
int sz[MAXN],wt[MAXN];
int root;
vector<int> edge[MAXN];
void dfs(int x,int f){
sz[x]=1;
wt[x]=0;
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i];
if(y==f) continue;
dfs(y,x);
sz[x]+=sz[y];
wt[x]=max(wt[x],sz[y]);
}
wt[x]=max(wt[x],n-sz[x]);
if(wt[x]<wt[root]){
root=x;
}
}
树的直径
#include<bits/stdc++.h>
#define MAXN 105
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n,m;
struct node{
int to,val;
};
vector<node> edge[MAXN];
long long dis[MAXN];
int s,e;
void dfs(int x,int f){
for(int i=0;i<edge[x].size();i++){
int y=edge[x][i].to;
int w=edge[x][i].val;
if(y==f) continue;
dis[y]=dis[x]+w;
if(dis[y]>dis[e]){
e=y;
}
dfs(y,x);
}
}
int main(){
//freopen("","r",stdin);
//freopen("","w",stdout);
n=read();m=read();
int u,v,w;
for(int i=1;i<=m;i++){
u=read();v=read();w=read();
edge[u].push_back((node){v,w});
edge[v].push_back((node){u,w});
}
dfs(1,0);
memset(dis,0,sizeof(dis));
s=e;
e=0;
dfs(s,0);
printf("%d %d\n",s,e);
return 0;
}
树链剖分
#include<bits/stdc++.h>
#define MAXN 100005
#define int long long
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n,m,rt,mod;
vector<int> edge[MAXN];
int a[MAXN],w[MAXN];
int fa[MAXN],dep[MAXN],sz[MAXN],son[MAXN],top[MAXN],dfn[MAXN],tot;
void dfs1(int x,int f){
fa[x]=f;
dep[x]=dep[f]+1;
sz[x]=1;
for(auto y:edge[x]){
if(y==f) continue;
dfs1(y,x);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int f,int tp){
top[x]=tp;
dfn[x]=++tot;
w[tot]=a[x];
if(son[x]) dfs2(son[x],x,tp);
for(auto y:edge[x]){
if(y==f || y==son[x]) continue;
dfs2(y,x,y);
}
}
struct segment_tree{
#define ls k<<1
#define rs k<<1|1
struct node{
int l,r;
int sum,tag;
}t[MAXN<<2];
void pushup(int k){
t[k].sum=(t[ls].sum+t[rs].sum)%mod;
}
void pushtag(int k,int v){
(t[k].sum+=v*(t[k].r-t[k].l+1))%=mod;
(t[k].tag+=v)%=mod;
}
void pushdown(int k){
if(t[k].tag){
pushtag(ls,t[k].tag);
pushtag(rs,t[k].tag);
t[k].tag=0;
}
}
void build(int k,int l,int r){
t[k].l=l;t[k].r=r;
if(l==r){
t[k].sum=w[l]%mod;
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(k);
}
void update(int k,int l,int r,int v){
if(t[k].l>=l && t[k].r<=r){
pushtag(k,v);
return;
}
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if(mid>=l) update(ls,l,r,v);
if(mid<r) update(rs,l,r,v);
pushup(k);
}
int query(int k,int l,int r){
if(t[k].l>=l && t[k].r<=r){
return t[k].sum;
}
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
int res=0;
if(mid>=l) res=(res+query(ls,l,r))%mod;
if(mid<r) res=(res+query(rs,l,r))%mod;
return res;
}
}ST;
void update(int a,int b,int v){
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]]) swap(a,b);
ST.update(1,dfn[top[a]],dfn[a],v);
a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
ST.update(1,dfn[a],dfn[b],v);
}
int query(int a,int b){
int res=0;
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]]) swap(a,b);
(res+=ST.query(1,dfn[top[a]],dfn[a]))%=mod;
a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
(res+=ST.query(1,dfn[a],dfn[b]))%=mod;
return res;
}
void upd(int x,int v){
ST.update(1,dfn[x],dfn[x]+sz[x]-1,v);
}
int qry(int x){
return ST.query(1,dfn[x],dfn[x]+sz[x]-1);
}
bool M2;
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int Time=clock();
n=read();m=read();
rt=read();mod=read();
for(int i=1;i<=n;i++){
a[i]=read();
}
int u,v;
for(int i=1;i<n;i++){
u=read();v=read();
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs1(rt,0);
dfs2(rt,0,rt);
ST.build(1,1,n);
int op,x,y;
while(m--){
op=read();
if(op==1){
x=read();y=read();v=read();
update(x,y,v);
}else if(op==2){
x=read();y=read();
printf("%lld\n",query(x,y));
}else if(op==3){
x=read();v=read();
upd(x,v);
}else{
x=read();
printf("%lld\n",qry(x));
}
}
look_memory;
look_time;
return 0;
}
长链剖分
k级祖先
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
#define ui unsigned int
ui s;
inline ui get(ui x) {
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return s = x;
}
int n,q;
vector<int> edge[MAXN];
int fa[MAXN][25],dep[MAXN],len[MAXN],son[MAXN],top[MAXN];
long long Ans;
int lg[MAXN];
vector<int> U[MAXN],D[MAXN];
void dfs1(int x,int f){
fa[x][0]=f;
dep[x]=dep[f]+1;
for(auto y:edge[x]){
if(y==f) continue;
dfs1(y,x);
if(len[y]>len[son[x]]) son[x]=y;
}
len[x]=len[son[x]]+1;
}
void dfs2(int x,int f,int tp){
top[x]=tp;
if(x==tp){
int now=x;
U[x].resize(len[x]+10);
D[x].resize(len[x]+10);
for(int i=0;i<len[x];i++){
U[x][i]=now;
now=fa[now][0];
}
now=x;
for(int i=0;i<len[x];i++){
D[x][i]=now;
now=son[now];
}
}
if(son[x]) dfs2(son[x],x,tp);
for(auto y:edge[x]){
if(y==f || y==son[x]) continue;
dfs2(y,x,y);
}
}
void init(){
lg[1]=0;
for(int i=2;i<=n;i++){
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=21;j++){
for(int i=1;i<=n;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int get_kth(int x,int k){
if(!k) return x;
x=fa[x][lg[k]];
k-=1<<lg[k];
k-=dep[x]-dep[top[x]];
x=top[x];
if(k>=0) return U[x][k];
else return D[x][-k];
}
int main(){
n=read();q=read();
scanf("%u",&s);
int f,rt;
for(int i=1;i<=n;i++){
f=read();
if(!f){
rt=i;
}
edge[f].push_back(i);
edge[i].push_back(f);
}
dfs1(rt,0);
dfs2(rt,0,rt);
init();
int ans=0;
int x,k;
for(int i=1;i<=q;i++){
x=((get(s)^ans)%n)+1;
k=(get(s)^ans)%dep[x];
ans=get_kth(x,k);
Ans^=1ll*ans*i;
}
printf("%lld",Ans);
return 0;
}
长剖优化DP
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int n;
vector<int> edge[MAXN];
int dep[MAXN],len[MAXN],son[MAXN];
long long *f[MAXN],*g[MAXN];
long long base[MAXN<<2],*p=base;
long long ans;
void dfs1(int x,int ff){
dep[x]=dep[ff]+1;
for(auto y:edge[x]){
if(y==ff) continue;
dfs1(y,x);
if(len[y]>len[son[x]]) son[x]=y;
}
len[x]=len[son[x]]+1;
}
void dfs(int x,int ff){
if(son[x]){
f[son[x]]=f[x]+1;
g[son[x]]=g[x]-1;
dfs(son[x],x);
}
ans+=g[x][0];
f[x][0]=1;
for(auto y:edge[x]){
if(y==ff || y==son[x]) continue;
f[y]=p;
p+=len[y]<<1;
g[y]=p;
p+=len[y]<<1;
dfs(y,x);
for(int i=0;i<len[y];i++){
if(i) ans+=f[x][i-1]*g[y][i];
ans+=g[x][i+1]*f[y][i];
}
for(int i=0;i<len[y];i++){
g[x][i+1]+=f[x][i+1]*f[y][i];
if(i) g[x][i-1]+=g[y][i];
}
for(int i=0;i<len[y];i++){
f[x][i+1]+=f[y][i];
}
}
}
int main(){
n=read();
int u,v;
for(int i=1;i<n;i++){
u=read();v=read();
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs1(1,0);
f[1]=p;
p+=len[1]<<1;
g[1]=p;
p+=len[1]<<1;
dfs(1,0);
printf("%lld",ans);
return 0;
}
DSU On Tree
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
int n,m;
vector<int> edge[MAXN];
int c[MAXN],cnt;
bool mark[MAXN];
int dep[MAXN],sz[MAXN],son[MAXN];
int ans[MAXN];
void dfs(int x,int f){
dep[x]=dep[f]+1;
sz[x]=1;
son[x]=0;
for(auto y:edge[x]){
if(y==f) continue;
dfs(y,x);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]]){
son[x]=y;
}
}
}
void clear(int x,int f){
mark[c[x]]=false;
for(auto y:edge[x]){
if(y==f) continue;
clear(y,x);
}
}
void dfs2(int x,int f,int id){
if(!mark[c[x]]){
mark[c[x]]=true;
cnt++;
}
for(auto y:edge[x]){
if(y==f || y==son[id]) continue;
dfs2(y,x,id);
}
}
void dfs1(int x,int f){
for(auto y:edge[x]){
if(y==f || y==son[x]) continue;
dfs1(y,x);
clear(y,x);
cnt=0;
}
if(son[x]) dfs1(son[x],x);
dfs2(x,f,x);
ans[x]=cnt;
}
int main(){
n=read();
int u,v;
for(int i=1;i<n;i++){
u=read();v=read();
edge[u].push_back(v);
edge[v].push_back(u);
}
for(int i=1;i<=n;i++){
c[i]=read();
}
dfs(1,0);
dfs1(1,0);
m=read();
int x;
while(m--){
x=read();
printf("%d\n",ans[x]);
}
return 0;
}
DP
01背包
完全背包
多重背包
数位DP
区间DP(例题)
树形DP(例题)
换根DP(例题)
状压DP(例题)
数论
线性筛
int n,q;
int prime[10000005] ,cnt;
bool ntp[MAXN];
void xxs(){
for(int i=2;i<=n;i++){
if(!ntp[i]){
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
ntp[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
- GCD
int GCD(int a,int b){
if(b==0) return a;
return GCD(b,a%b);
}
逆元
inv[1]=1;
for(int i=2;i<=n;i++){
inv[i]=(p-p/i)*inv[p%i]%p;
}
mul[0]=mul[1]=1;
for(int i=2;i<=n;i++){
mul[i]=mul[i-1]*i%p;
}
inv[n]=qpow(mul[n],p-2);
for(int i=n-1;i>=1;i--){
inv[i]=inv[i+1]*(i+1)%p;
}
线性基
#include<bits/stdc++.h>
#define MAXN 105
#define int long long
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n;
int a[MAXN];
long long s[100];
const int logn=60;
long long ans;
bool insert(long long x){
for(int i=logn;i>=0;i--){
if(x&(1ll<<i)){
if(!s[i]){
for(int j=i;j>=0;j--){
if(x&(1ll<<j)) x^=s[j];
}
s[i]=x;
for(int j=logn;j>i;j--){
if(s[j]&(1ll<<i)) s[j]^=s[i];
}
return true;
}else{
x^=s[i];
}
}
}
return false;
}
long long get_max(){
long long res=0;
for(int i=logn;i>=0;i--){
if(res^s[i]>res) res^=s[i];
}
return res;
}
bool M2;
signed main(){
// freopen("","r",stdin);
// freopen("","w",stdout);
int Time=clock();
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
insert(a[i]);
}
ans=get_max();
printf("%lld\n",ans);
look_memory;
look_time;
return 0;
}
字符串
哈希
trie树
#include<bits/stdc++.h>
#define MAXN 3000006
using namespace std;
inline int read(){
int x=0;
char c=getchar();
while(c<'0' || c>'9'){
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
int T;
int n,q;
int trie[MAXN][70],tot;
int cnt[MAXN];
char s[MAXN];
int get_val(char c){
if(c>='a' && c<='z') return c-'a';
if(c>='A' && c<='Z') return c-'A'+26;
if(c>='0' && c<='9') return c-'0'+52;
}
void insert(char str[]){
int len=strlen(str);
int p=0;
for(int i=0;i<len;i++){
int c=get_val(str[i]);
if(!trie[p][c]) trie[p][c]=++tot;
p=trie[p][c];
cnt[p]++;
}
}
int search(char str[]){
int len=strlen(str);
int p=0;
for(int i=0;i<len;i++){
int c=get_val(str[i]);
if(!trie[p][c]) return 0;
p=trie[p][c];
}
return cnt[p];
}
int main(){
// printf("!");
T=read();
while(T--){
for(int i=0;i<=tot;i++){
for(int j=0;j<=70;j++){
trie[i][j]=0;
}
cnt[i]=0;
}
tot=0;
n=read();q=read();
for(int i=1;i<=n;i++){
scanf("%s",s);
insert(s);
}
for(int i=1;i<=q;i++){
scanf("%s",s);
int ans=search(s);
printf("%d\n",ans);
}
}
return 0;
}
KMP
#include<bits/stdc++.h>
#define MAXN 1000005
using namespace std;
char a[MAXN],b[MAXN];
int nxt[MAXN];
int main(){
cin>>a+1;
cin>>b+1;
int la=strlen(a+1);
int lb=strlen(b+1);
int j=0;
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-j+1);
}
}
for(int i=1;i<=lb;i++){
printf("%d ",nxt[i]);
}
return 0;
}
AC自动机
#include<bits/stdc++.h>
#define MAXN 200005
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n;
char s[MAXN*10],t[MAXN];
int pos[MAXN];
int ch[MAXN][30],fail[MAXN],tot;
bool ky[MAXN];
int cnt[MAXN];
int id[MAXN],idx;
int rt=0;
queue<int> q;
void insert(char s[],int id){
int len=strlen(s+1);
int x=rt;
for(int i=1;i<=len;i++){
int w=s[i]-'a';
if(!ch[x][w]) ch[x][w]=++tot;
x=ch[x][w];
}
pos[id]=x;
}
void bfs(){
for(int i=0;i<26;i++){
if(ch[rt][i]) q.push(ch[rt][i]);
}
while(!q.empty()){
int x=q.front();
q.pop();
id[++idx]=x;
for(int i=0;i<26;i++){
if(ch[x][i]){
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}else{
ch[x][i]=ch[fail[x]][i];
}
}
}
}
void query(char s[]){
int x=rt;
int len=strlen(s+1);
for(int i=1;i<=len;i++){
int w=s[i]-'a';
x=ch[x][w];
cnt[x]++;
}
}
void topo(){
for(int i=idx;i>=1;i--){
cnt[fail[id[i]]]+=cnt[id[i]];
}
}
bool M2;
int main(){
// freopen("","r",stdin);
// freopen("","w",stdout);
int Time=clock();
n=read();
for(int i=1;i<=n;i++){
scanf("%s",t+1);
insert(t,i);
}
bfs();
scanf("%s",s+1);
query(s);
topo();
for(int i=1;i<=n;i++){
printf("%d\n",cnt[pos[i]]);
}
return 0;
}
后缀数组(SA)
#include<bits/stdc++.h>
#define MAXN 2000050
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n,k;
char s[MAXN];
int rk[MAXN],sa[MAXN];
int hr[MAXN],hs[MAXN];
int bn[MAXN],tmp[MAXN];
bool M2;
int main(){
// freopen("","r",stdin);
// freopen("","w",stdout);
int Time=clock();
scanf("%s",s+1);
n=strlen(s+1);
k=max(n,255);
for(int i=1;i<=n;i++){
rk[i]=s[i];
bn[rk[i]]++;
}
for(int i=1;i<=k;i++){
bn[i]+=bn[i-1];
}
for(int i=1;i<=n;i++){
sa[bn[rk[i]]]=i;
bn[rk[i]]--;
}
for(int j=1;j<=n;j<<=1){
int cnt=0;
for(int i=n-j+1;i<=n;i++){
tmp[++cnt]=i;
}
for(int i=1;i<=n;i++){
if(sa[i]-j>0) tmp[++cnt]=sa[i]-j;
}
for(int i=1;i<=k;i++){
bn[i]=0;
}
for(int i=1;i<=n;i++){
bn[rk[i]]++;
}
for(int i=1;i<=k;i++){
bn[i]+=bn[i-1];
}
for(int i=n;i>=1;i--){
sa[bn[rk[tmp[i]]]]=tmp[i];
bn[rk[tmp[i]]]--;
}
tmp[sa[1]]=1;
for(int i=2;i<=n;i++){
int t=(rk[sa[i]]!=rk[sa[i-1]]) | (rk[sa[i]+j]!=rk[sa[i-1]+j]);
tmp[sa[i]]=tmp[sa[i-1]]+t;
}
for(int i=1;i<=n;i++){
rk[i]=tmp[i];
}
if(rk[sa[n]]==n) break;
}
for(int i=1;i<=n;i++){
printf("%d ",sa[i]);
}puts("");
look_memory;
look_time;
return 0;
}
后缀自动机(SAM)
#include<bits/stdc++.h>
#define MAXN 2000005
#define look_memory cerr<<abs(&M2-&M1)/1024.0/1024<<'\n'
#define look_time cerr<<(clock()-Time)*1.0/CLOCKS_PER_SEC<<'\n'
using namespace std;
inline int read(){
int x=0;
int f=1;
char c=getchar();
while(c<'0' || c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0' && c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
bool M1;
int n;
char s[MAXN];
long long ans;
int fa[MAXN],ch[MAXN][27],sz[MAXN],mx[MAXN],lst,tot;
int bn[MAXN],topo[MAXN];
void push(int x){
int p=lst,np=++tot;
lst=np;
mx[np]=mx[p]+1;
sz[np]=1;
while(p && !ch[p][x]){
ch[p][x]=np;
p=fa[p];
}
if(!p) fa[np]=1;
else{
int q=ch[p][x];
if(mx[q]==mx[p]+1) fa[np]=q;
else{
int nq=++tot;
mx[nq]=mx[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
while(ch[p][x]==q){
ch[p][x]=nq;
p=fa[p];
}
}
}
}
void build(){
tot=lst=1;
for(int i=1;i<=n;i++){
push(s[i]-'a');
}
for(int i=1;i<=tot;i++){
bn[mx[i]]++;
}
for(int i=1;i<=n;i++){
bn[i]+=bn[i-1];
}
for(int i=1;i<=tot;i++){
topo[bn[mx[i]]--]=i;
}
for(int i=tot;i>=1;i--){
sz[fa[topo[i]]]+=sz[topo[i]];
}
}
void solve(){
for(int i=1;i<=tot;i++){
if(sz[i]>1){
ans=max(ans,1ll*sz[i]*mx[i]);
}
}
}
bool M2;
signed main(){
// freopen("","r",stdin);
// freopen("","w",stdout);
int Time=clock();
scanf("%s",s+1);
n=strlen(s+1);
build();
solve();
printf("%lld\n",ans);
look_memory;
look_time;
return 0;
}

浙公网安备 33010602011771号