省选模板大杂烩
Code:
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>
#include <algorithm>
#define maxn 1000000
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
//动态树
namespace LCT{
int ch[maxn][2];
int tag[maxn],lazy[maxn];
int sta[maxn];
int sumv[maxn];
int siz[maxn];
int maxv[maxn],minv[maxn];
int lson(int x){ return ch[x][0]; }
int rson(int x){ return ch[x][1]; }
int get(int x) { return ch[f[x]][1] == x; }
int isRoot(int x){ return !(ch[f[x]][1]==x||ch[f[x]][0]==x); }
void addv(int x,int delta){
sumv[x] += siz[x] * delta;
lazy[x] += delta;
}
void rev(int x){
tag[x] ^= 1;
if(tag[x])
swap(ch[x][0],ch[x][1]),tag[x] = 0;
}
void pushdown(int x){
if(lazy[x]) {
addv(lson(x),lazy[x]);
addv(rson(x),lazy[x]);
lazy[x] = 0;
}
if(tag[x])rev(lson(x)),rev(rson(x)),tag[x] = 0;
}
void pushup(int x){
sumv[x] = sumv[lson(x)] + sumv[rson(x)] + val[x];
siz[x] = siz[lson(x)] + siz[rson(x)] + 1;
maxv[x] = max(maxv[lson(x)],maxv[rson(x)]);
minv[x] = min(minv[son(x)],minv[rson(x)]);
}
void rotate(int x){
int old=f[x],oldf=f[old],which=get(x);
if(!isRoot(old)) ch[oldf][ch[oldf][1]==old] = x;
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1] = old,f[old] = x,f[x] = oldf;
pushup(old),pushup(x);
}
void splay(int x){
int v=0,u=x;
sta[++v] = x;
while(!isRoot(u)) sta[++v] = f[u],u=f[u];
while(v) pushdown(sta[v--]);
u=f[u];
for(int fa;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u) rotate(get(fa)==get(x) ? fa: x);
}
void Access(int x){
for(int y=0;x;y=x,x=f[x])
splay(x),ch[x][1]=y;
}
void makeRoot(int x){
Access(x),splay(x),rev(x);
}
void link(int x,int y){
makeRoot(x),f[x]=y;
}
//x为y的父亲
void cut(int x,int y){
makeRoot(x),Access(y),splay(y);
ch[y][0]=f[ch[y][0]]=0;
pushup(y);
}
};
//树状数组
namespace BIT{
int n;
int C[maxn];
int lowbit(int t) { return t & (-t); }
void update(int x,int delta){
while(x <= n) {
C[x] += delta;
x += lowbit(x);
}
}
int query(int x){
int sum=0;
while(x >= 0) sum += C[x],x -= lowbit(x);
return sum;
}
};
//主席树(不修改)
namespace Chair_Tree1{
int node_cnt;
int ls[maxn],rs[maxn];
int sumv[maxn];
void build(int l,int r,int &o){
if(l>r) return;
o=++node_cnt;
if(l==r) return ;
int mid=(l+r)>>1;
build(l,mid,ls[o]);
build(mid+1,r,rs[o]);
}
int update(int l,int r,int k,int o){
int oo=++node_cnt;
sumv[oo] = sumv[o] + 1;
ls[oo] = ls[o];
rs[oo] = rs[o];
if(l==r) return oo;
int mid=(l+r)>>1;
if(k<=mid) ls[oo] = update(l,mid,k,ls[o]);
else rs[oo] = update(mid+1,r,k,rs[o]);
return oo;
}
int query(int u,int v,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>1;
int delta = sumv[ls[v]] - sumv[ls[u]];
if(delta >= k) return query(ls[u],ls[v],l,mid,k);
else return query(rs[u],rs[v],mid+1,r,k-delta);
}
};
//主席树2(修改)
namespace Chair_Tree2{
struct Queries{
int c,l,r,k;
Queries(int c=0,int l=0,int r=0,)
}asks[maxn];
int lson[maxn*10],rson[maxn*10],root[maxn];
int temp[2][200],count[2],sumv[maxn*10];
int cnt_Tree;
int lowbit(int t){ return t & (-t); }
void insert(int l,int r,int pos,int delta,int &o){
if(!o) o=++cnt_Tree;
sumv[o] += delta;
if(l==r) return ;
int mid=(l+r)>>1;
if(pos<=mid)
insert(l,mid,pos,delta,lson[o]);
else
insert(mid+1,r,pos,delta,rson[o]);
}
void update(int pos,int val,int delta){
for(int i=pos;i<=n;i+=lowbit(i))
insert(1,n,val,delta,root[i]);
}
int query(int l,int r,int k){
if(l==r) return l;
int sum=0;
for(int i=1;i<=count[0];++i) sum+=sumv[lson[temp[0][i]]];
for(int i=1;i<=count[1];++i) sum-=sumv[lson[temp[1][i]]];
int mid=(l+r)>>1;
if(k<=sum){
for(int i=1;i<=count[0];++i) temp[0][i]=lson[temp[0][i]];
for(int i=1;i<=count[1];++i) temp[1][i]=lson[temp[1][i]];
return query(l,mid,k);
}
else {
for(int i=1;i<=count[0];++i) temp[0][i]=rson[temp[0][i]];
for(int i=1;i<=count[1];++i) temp[1][i]=rson[temp[1][i]];
return query(mid+1,r,k-sum);
}
}
int Query(int l,int r,int k){
memset(temp,0,sizeof(temp));
count[0]=count[1]=0;
for(int i=r;i>=1;i-=lowbit(i))
temp[0][++count[0]] = root[i];
for(int i=l-1;i>=1;i-=lowbit(i))
temp[1][++count[0]] = root[i];
return query(1,n,k);
}
};
//并查集
namespace Union_Find{
int n;
int p[maxn];
void init(){
for(int i=1;i<=n;++i) p[i]=i;
}
int find(int x){
return p[x]==x?x:p[x] = find(p[x]);
}
void merge(int a,int b){
int x=find(a),y=find(b);
if(x==y) return;
p[x] = y;
}
};
//可并堆
namespace M_heap{
int val[maxn];
int ch[maxn][2];
int dis[maxn];
int siz[maxn];
int merge(int a,int b){
if(!a||!b) return a + b;
if(val[a] < val[b]) swap(a,b);
ch[a][1] = merge(ch[a][1],b);
if(dis[ch[a][1]]>dis[ch[a][0]]) swap(ch[a][0],ch[a][1]);
dis[a] = dis[ch[a][0]] + 1;
sumv[a] = sumv[ch[a][0]] + sumv[ch[a][1]] + val[a];
siz[a] = siz[ch[a][0]] + siz[ch[a][1]] + 1;
return a;
}
void pop(int &a){
int t=merge(ch[a][0],ch[a][1]);
siz[a] = sumv[a] = val[a] = ch[a][0] = ch[a][1] = 0;
a=t;
}
};
//线段树
namespace Segment_Tree{
#define ll long long
long long mod;
int val[maxn];
ll sumv[maxn<<2],mult[maxn<<2],addv[maxn<<2];
void pushdown(int o,int l,int r){
int mid=(l+r)>>1,ls=(o<<1),rs=(o<<1)|1;
if(mult[o]!=1) {
sumv[ls] = (sumv[ls] * mult[o])%mod;
sumv[rs] = (sumv[rs] * mult[o])%mod;
mult[ls] = (mult[ls] * mult[o])%mod;
mult[rs] = (mult[rs] * mult[o])%mod;
addv[ls] = (addv[ls] * mult[o])%mod;
addv[rs] = (addv[rs] * mult[o])%mod;
mult[o] = 1;
}
if(addv[o] != 0) {
if(mid>=l) sumv[ls] += (mid-l+1) *addv[o];
if(mid+1<=r) sumv[rs] += (r-mid) * addv[o];
addv[ls] += addv[o],addv[rs] += addv[o];
addv[o]=0;
}
}
void build_Tree(int l,int r,int o){
if(l>r) return;
mult[o]=1;
if(l==r) {
sumv[o] = val[l]%mod;
return;
}
int mid=(l+r)>>1,ls=(o<<1),rs=(o<<1)|1;
build_Tree(l,mid,ls);
build_Tree(mid+1,r,rs);
sumv[o] = (sumv[ls] + sumv[rs])%mod;
}
void update_mult(int l,int r,int o,int L,int R,int delta){
if(l > r || r < L || l > R) return;
if(l>=L&&r<=R) {
sumv[o]*=delta;
mult[o]*=delta;
addv[o]*=delta;
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
update_mult(l,mid,(o<<1),L,R,delta);
update_mult(mid+1,r,(o<<1)|1,L,R,delta);
sumv[o] = sumv[(o<<1)] + sumv[(o<<1)|1];
}
void update_add(int l,int r,int o,int L,int R,int delta) {
if(l > r || r < L || l > R) return;
if(l>=L&&r<=R){
sumv[o]+=delta*(r-l+1);
addv[o]+=delta;
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
update_add(l,mid,(o<<1),L,R,delta);
update_add(mid+1,r,(o<<1)|1,L,R,delta);
sumv[o] = sumv[(o<<1)] + sumv[(o<<1)|1];
}
int query(int l,int r,int o,int L,int R){
if(l > r || r < L || l > R) return 0;
if(l >= L && r <= R) return sumv[o];
int mid=(l+r)>>1;
pushdown(o,l,r);
return query(l,mid,(o<<1),L,R)+query(mid+1,r,(o<<1)|1,L,R);
}
};
//树链剖分
namespace Heavy_Edge{
#define ll long long
#define lson (o<<1)
#define rson (o<<1)|1
ll mod;
int n;
int head[maxn],nex[maxn<<1],to[maxn<<1];
int p[maxn],son[maxn],dep[maxn],top[maxn];
int cnt,cnt2;
ll sumv[maxn<<2];
int lazy[maxn];
int A[maxn],st[maxn],ed[maxn],val[maxn];
void addedge(int u,int v){
nex[++cnt]=head[u],head[u]=cnt,to[cnt]= v;
}
void dfs1(int u,int fa,int cur){
p[u]=fa,dep[u]=cur,siz[u]=1;
for(int i=head[u];i;i=nex[i])
if(to[i]!=fa) {
dfs1(to[i],u,cur+1);
siz[u]+=siz[to[i]];
if(son[u]==-1||siz[to[i]]>siz[son[u]])
son[u] = to[i];
}
}
void dfs2(int u,int tp){
top[u]=tp,A[u]=++cnt2,st[u]=cnt2;
if(son[u]!=-1) dfs2(son[u],tp);
for(int i=head[u];i;i=nex[i])
if(to[i]!=p[u]&&to[i]!=son[u])
dfs2(to[i],to[i]);
ed[u]=cnt2;
}
void pushdown(int l,int r,int o){
if(lazy[o]){
int mid=(l+r)>>1;
lazy[lson]+=lazy[o],lazy[rson]+=lazy[o];
sumv[lson]+=(mid-l+1)*lazy[o];
sumv[rson]+=(r-mid)*lazy[o];
lazy[o]=0;
}
}
void build(int l,int r,int o,int arr[]){
if(l>r) return;
if(l==r) {
sumv[o]=arr[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,lson,arr);
build(mid+1,r,rson,arr);
sumv[o] = sumv[lson] + sumv[rson];
}
void update(int l,int r,int k,int L,int R,int o){
if(l>r||r<L||l>R) return;
if(l>=L&&r<=R){
lazy[o]+=k;
sumv[o]+=(r-l+1)*k;
return;
}
int mid=(l+r)>>1;
pushdown(l,r,o);
update(l,mid,k,L,R,lson);
update(mid+1,r,k,L,R,rson);
sumv[o] = sumv[lson] + sumv[rson];
}
long long query(int l,int r,int o,int L,int R){
if(l>r||r<L||l>R) return 0;
if(l>=L&&r<=R) return sumv[o];
int mid=(l+r)>>1;
pushdown(l,r,o);
return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
}
void up(int x,int y,int del){
while(top[x]!=top[y]){
if(dep[top[x]>dep[top[y]]) swap(x,y);
update(1,n,del,A[top[y]],A[y],1);
}
if(dep[x]<dep[y]) swap(x,y);
update(1,n,del,A[y],A[x],1);
}
long long look_up(int x,int y){
long long sum=0;
while(top[x]!=top[y]) {
if(dep[top[x]]>dep[top[y]]) swap(x,y);
sum+=query(1,n,1,A[top[y]],A[y]);
y=p[top[y]];
}
if(dep[y]>dep[x]) swap(x,y);
sum+=query(1,n,1,A[y],A[x];
return sum;
}
};
//最近公共祖先
namespace LCA{
#define LOG 21
int cnt;
int f[22][maxn],dep[maxn];
int head[maxn],to[maxn],nex[maxn];
void addedge(int u,int v){
nex[++cnt] = head[u],head[u]=cnt,to[cnt] = v;
}
void dfs(int u,int fa){
dep[u] = dep[fa] + 1;
f[0][u]=fa;
for(int i=1;i<LOG;++i) f[i][u]=f[i-1][f[i-1][u]];
for(int i=head[u];i;i=nex[i])
if(to[i]!=fa)dfs(to[i],u);
}
int query(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
if(dep[x]!=dep[y]){
for(int i=LOG-1;i>=0;--i)
if(dep[f[i][y]]<=dep[x]) y=f[i][y];
}
if(x==y) return x;
for(int i=LOG-1;i>=0;--i)
if(f[i][x]!=f[i][y])
x=f[i][x],y=f[i][y];
return f[0][x];
}
};
//线性筛(欧拉函数,莫比乌斯函数)
namespace get_prime{
int tot;
int prime[maxn],is[maxn];
int mu[maxn],phi[maxn];
void get_prime(){
mu[1]=1;
phi[1]=1;
for(int i=2;i<maxn;++i){
if(!is[i]) {
prime[++tot]=i;
phi[i]=i-1;
mu[i]=-1;
}
for(int j=1;j<=cnt&&prime[j]*i<maxn;++j){
is[prime[j]*i]=1;
if(i%prime[j]!=0) {
phi[i*prime[j]]=phi[i]*(prime[j]-1);
mu[i*prime[j]]=-mu[i];
}
else {
phi[i*prime[j]]=prime[j]*phi[i];
mu[i*prime[j]]=0;
break;
}
}
}
}
};
// CF666E 权值线段树+广义后缀自动机+倍增
namespace CF666E{
};