基本
快读
inline void read(int &n)
{
n=0;bool b=0;
char c=getchar();
while(c<'0'||c>'9'){c=getchar();if(c=='-')b=1;}
while(c>='0'&&c<='9') n=n*10+c-48,c=getchar();
if(b) n=-n;
}
图论
tarjan
//强连通分量
void dfs(int now,int fa)
{
dfn[now]=low[now]=++Time;
instack[now]=1;
s.push(now);
for(int i=head[now];i;i=a[i].nxt)
if(!dfn[a[i].to])
{
dfs(a[i].to,now);
low[now]=min(low[now],low[a[i].to]);
}
else if(instack[a[i].to]) low[now]=min(low[now],dfn[a[i].to]);
if(dfn[now]==low[now])
{
tot++;
int tmp;
do
{
tmp=s.top();
instack[tmp]=0;
}while(tmp!=now);
}
}
//缩点
void dfs(int now)
{
low[now]=dfn[now]=++Time;
s[++top]=now;
instack[now]=1;
for(int i=head[now];i;i=a[i].nxt)
if(!dfn[a[i].to])
{
dfs(a[i].to);
low[now]=min(low[now],low[a[i].to]);
}
else if(instack[a[i].to]) low[now]=min(low[now],dfn[a[i].to]);
if(low[now]==dfn[now])
{
int tmp;
tot++;
do
{
tmp=s[top--];
instack[tmp]=0;
block[tmp]=tot;
size[tot]++;
}while(tmp!=now);
}
}
//LCA
int find(int n)
{
if(f[n]!=n) f[n]=find(f[n]);
return f[n];
}
void dfs(int now,int depth)
{
f[now]=now;
vis[now]=1;
deep[now]=depth;
for(int i=head[now];i;i=a[i].nxt)
if(!vis[a[i].to])
{
dfs(a[i].to,depth+a[i].dis);
f[a[i].to]=now;
}
for(int i=Head[now];i;i=ask[i].nxt)
if(vis[ask[i].to]) ans[ask[i].id]=deep[now]+deep[ask[i].to]-(deep[find(ask[i].to)]<<1);
}
求RMQ
//h==0:取[l,r]的最大值h==1:取[l,r]的最小值
#include<cstdio>
#include<cmath>
#include<cstring>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
int n,i,j,l,r,x,h;
int a[10001];
int f[10001][15];
int ff[10001][15];
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(ff,10,sizeof(ff));
for(i=1;i<=n;i++)
{
f[i][0]=a[i];
ff[i][0]=a[i];
}
for(j=1;j<=log(n)/log(2);j++)
for(i=1;i<=n+1-(1<<j);i++)
{
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
ff[i][j]=min(ff[i][j-1],ff[i+(1<<(j-1))][j-1]);
}
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&h,&l,&r);
x=log(r-l+1)/log(2);
if(h==0) printf("%d\n",max(f[l][x],f[r+1-(1<<x)][x]));
else printf("%d\n",min(ff[l][x],ff[r+1-(1<<x)][x]));
}
return 0;
}
网络流
inline bool bfs(int s,int t)
{
memset(deep,0,sizeof(deep));
q.clear();
q.push(s);
deep[s]=1;
while(!q.empty())
{
int tmp=q.front();
q.pop();
for(int i=head[tmp];i;i=a[i].next)
if(a[i].remain&&!deep[a[i].to]) deep[a[i].to]=deep[tmp]+1,q.push(a[i].to);
}
return deep[t];
}
int dfs(int now,int t,int limit)
{
if(now==t) return limit;
int flow=0,f;
for(int i=head[now];i;i=a[i].next)
if(a[i].remain&&deep[a[i].to]==deep[now]+1)
{
f=dfs(a[i].to,t,min(a[i].remain,limit));
a[i].remain-=f;
a[i^1].remain+=f;
limit-=f;
flow+=f;
if(!limit) return flow;
}
deep[now]=-1;
return flow;
}
inline int dinic(int s,int t)
{
int ans=0;
while(bfs(s,t)) ans+=dfs(s,t,INF);
return ans;
}
费用流
inline bool SPFA()
{
memset(dis,10,sizeof(dis));
dis[S]=0;
u[S]=INF;
q.push(S),b[S]=1;
while(!q.empty())
{
int tmp=q.front();q.pop();
for(int i=head[tmp];i;i=a[i].next)
if(dis[a[i].to]>dis[tmp]+a[i].cost&&a[i].remain)
{
f[a[i].to]=tmp;
u[a[i].to]=min(u[tmp],a[i].remain);
dis[a[i].to]=dis[tmp]+a[i].cost;
if(!b[a[i].to]) q.push(a[i].to),b[a[i].to]=1;
}
}
if(dis[T]>INF) return 0;
ll p=T;
while(p!=S)
{
a[f[p]].remain-=u[T];
a[f[p]^1].remain+=u[T];
p=a[f[p]^1].to;
}
ans+=u[T]*dis[T];
return 1;
}
inline void mcmf(){while(SPFA());}
莫队
#include<bits/stdc++.h>
using namespace std;
struct node
{
int l,r,id;
}q[200010];
int a[50010];
int ans[200010];
int pos[200010];
int num[1000010];
int size,n,m,L=1,R,Ans;
inline bool cmp(node a,node b)
{
if(pos[a.l]==pos[b.l]) return a.r<b.r;
return pos[a.l]<pos[b.l];
}
int main()
{
scanf("%d",&n);
size=sqrt(n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),pos[i]=i/size;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++)
{
while(L<q[i].l) if(!--num[a[L++]]) Ans--;
while(L>q[i].l) if(!num[a[--L]]++) Ans++;
while(R<q[i].r) if(!num[a[++R]]++) Ans++;
while(R>q[i].r) if(!--num[a[R--]]) Ans--;
ans[q[i].id]=Ans;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
分块
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e6+10;
struct Block
{
int l,r,num,plus;
int a[1010];
inline void keep()
{
sort(a+1,a+num+1);
}
inline int find(int n)
{
int L=1,R=num,mid;
n-=plus;
while(L<R)
{
mid=(L+R)>>1;
if(a[mid]<n) L=mid+1;
else R=mid;
}
return L;
}
}a[1010];
int s[N];
int belong[N];
int n,q,x,y,z,ans,block,num;
char c;
inline void read(int &n)
{
n=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') n=n*10+c-48,c=getchar();
}
inline void build()
{
block=sqrt(n);
num=n/block;if(n%block) num++;
for(int i=1;i<=num;i++)
a[i].l=(i-1)*block+1,a[i].r=i*block,a[i].num=block;
a[num].r=n;a[num].num=a[num].r-a[num].l+1;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;
for(int i=1;i<=num;i++)
{
for(int j=a[i].l;j<=a[i].r;j++)
a[i].a[j-a[i].l+1]=s[j];
a[i].keep();
}
}
inline void add(int x,int y,int z)
{
if(belong[x]==belong[y])
{
for(int i=x;i<=y;i++)
s[i]+=z;
for(int i=a[belong[x]].l;i<=a[belong[x]].r;i++)
a[belong[x]].a[i-a[belong[x]].l+1]=s[i];
a[belong[x]].keep();
return;
}
for(int i=x;i<=a[belong[x]].r;i++)
s[i]+=z;
for(int i=a[belong[x]].l;i<=a[belong[x]].r;i++)
a[belong[x]].a[i-a[belong[x]].l+1]=s[i];
a[belong[x]].keep();
for(int i=belong[x]+1;i<belong[y];i++)
a[i].plus+=z;
for(int i=a[belong[y]].l;i<=y;i++)
s[i]+=z;
for(int i=a[belong[y]].l;i<=a[belong[y]].r;i++)
a[belong[y]].a[i-a[belong[y]].l+1]=s[i];
a[belong[y]].keep();
}
inline int ask(int x,int y,int z)
{
int ans=0;
if(belong[x]==belong[y])
{
for(int i=x;i<=y;i++)
if(s[i]+a[belong[x]].plus>=z) ans++;
return ans;
}
for(int i=x;i<=a[belong[x]].r;i++)
if(s[i]+a[belong[x]].plus>=z) ans++;
for(int i=belong[x]+1;i<belong[y];i++)
{
int p=a[i].find(z);
if(a[i].a[p]+a[i].plus>=z) ans+=a[i].num-p+1;
}
for(int i=a[belong[y]].l;i<=y;i++)
if(s[i]+a[belong[y]].plus>=z) ans++;
return ans;
}
int main()
{
read(n),read(q);
for(int i=1;i<=n;i++)
read(s[i]);
build();
while(q--)
{
c=getchar();
while(c!='A'&&c!='M') c=getchar();
read(x),read(y),read(z);
if(c=='A') printf("%d\n",ask(x,y,z));
else add(x,y,z);
}
return 0;
}
数论
Lucas&中国剩余定理&快速幂&扩展欧几里得&逆元
#include<cmath>
#include<cstdio>
typedef long long ll;
const ll M=999911659;
ll prime[5]={0,2,3,4679,35617};
ll fac[40000];
ll inv[40000];
ll a[5];
ll n,g,ans,x,y;
inline ll pow(ll a,ll b,ll p)
{
ll ans=1;
a%=p;
for(;b;b>>=1,a=1ll*a*a%p)
if(b&1) ans=1ll*ans*a%p;
return ans;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b) {x=1,y=0;return;}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
inline ll lucas(ll n,ll m,ll p)
{
ll ans=1;
while(n&&m)
{
ll a=n%p,b=m%p;
if(a<b) return 0;
ans=(1ll*ans*fac[a]*inv[fac[b]]*inv[fac[a-b]])%p;
n/=p,m/=p;
}
return ans;
}
int main()
{
scanf("%lld%lld",&n,&g);
inv[0]=1;fac[0]=1;fac[1]=1;
for(ll i=1;i<=4;i++)
{
for(ll j=1;j<=prime[i];j++)
{
fac[j]=(fac[j-1]*j)%prime[i];
inv[j]=pow(j,prime[i]-2,prime[i]);
}
for(ll j=1;j<=sqrt(n);j++)
if(!(n%j))
{
a[i]=(1ll*a[i]+lucas(n,j,prime[i]))%prime[i];
if(j*j<n) a[i]=(1ll*a[i]+lucas(n,n/j,prime[i]))%prime[i];
}
}
for(ll i=1;i<=4;i++)
{
exgcd((M-1)/prime[i],prime[i],x,y);
ans=(1ll*ans+1ll*a[i]*x*((M-1)/prime[i]))%(M-1);
}
ans=(ans%(M-1)+M-1)%(M-1);
if(!ans) ans=M-1;
printf("%lld",pow(g,ans,M));
return 0;
}
扩展中国剩余定理
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b){x=1,y=0;return;}
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
inline ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
inline ll inv(ll x,ll y)
{
ll x1,y1;exgcd(x,y,x1,y1);
return (x1%y+y)%y;
}
inline bool merge(ll m1,ll r1,ll m2,ll r2,ll &m3,ll &r3)
{
ll d=gcd(m1,m2),r=r2-r1;
if(r%d) return 0;
r=(r%m2+m2)%m2;
m1/=d,m2/=d;
r=r/d*inv(m1,m2)%m2*m1*d+r1;
m3=m1*m2*d,r3=(r%m3+m3)%m3;
return 1;
}
inline ll CRT()
{
ll m1=m[1],r1=r[1];
for(int i=2;i<=n;i++)
{
ll m2=m[i],r2=r[i],m3,r3;
if(!merge(m1,r1,m2,r2,m3,r3)) return -1;
m1=m3,r1=r3;
}
return (r1%m1+m1)%m1;
}
欧拉定理
线性求phi
inline void calc()
{
for(int i=1;i<n;i++)
phi[i]=i;
for(int i=2;i<n;i++)
{
if(phi[i]==i)
for(int j=i;j<n;j+=i)
phi[j]=(phi[j]/i)*(i-1);
ans+=phi[i];
}
ans++;
}
单点求phi
inline ll phi(ll N)
{
ll ans=N;
for(int i=2;i<=n;i++)
if(N%i==0)
{
ans=ans/i*(i-1);
while(N%i==0) N/=i;
}
if(N>1) ans=ans/N*(N-1);
return ans;
}
线性求逆元
inv[i]=1ll*(m-m/i)*inv[m%i]%m;
mobius反演&&(线性求mu值)
inline void mobius()
{
mu[1]=1;
for(int i=2;i<=100000;i++)
{
if(!Prime[i]) prime[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&prime[j]*i<=100000;j++)
{
Prime[prime[j]*i]=1;
if(i%prime[j]==0) break;
mu[prime[j]*i]=-mu[i];
}
}
for(int i=1;i<=100000;i++)
{
f[i].second=i;
for(int j=i;j<=100000;j+=i)
f[j].first+=i;
}
sort(f+1,f+100001);
}
inline void add(int pos,int num)
{
for(int i=pos;i<=100000;i+=lowbit(i))
a[i]+=num;
}
inline int ask(int pos)
{
int ans=0;
for(int i=pos;i;i-=lowbit(i))
ans+=a[i];
return ans;
}
inline int solve(int n,int m)
{
if(n>m) swap(n,m);
int ans=0;
for(int i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans+=(ask(last)-ask(i-1))*(n/i)*(m/i);
}
return ans;
}
高斯消元
for(int i=1;i<=n;i++)
{
int p=i;
for(int j=i+1;j<=n;j++)
if(fabs(f[j][i])>fabs(f[p][i])) p=j;
if(p!=i) for(int j=1;j<=n+1;j++)
swap(f[i][j],f[p][j]);
double tmp=f[i][i];
for(int j=1;j<=n+1;j++)
f[i][j]/=tmp;
for(int k=1;k<=n;k++)
if(k!=i)
{
tmp=f[k][i];
for(int j=1;j<=n+1;j++)
f[k][j]-=f[i][j]*tmp;
}
}
FFT
typedef complex<double> cp;
const double pi=acos(-1);
inline void FFT(cp *a,int f)
{
for(int i=0;i<n;i++)
if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<n;i<<=1)
{
cp wn(cos(pi/i),f*sin(pi/i));
for(int j=0,tmp=i<<1;j<n;j+=tmp)
{
cp w(1,0);
for(int k=0;k<i;k++,w*=wn)
{
cp x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y,a[j+k+i]=x-y;
}
}
}
}
bsgs
inline ll bsgs(ll x,ll z,ll p)
{
ma.clear(),x%=p;
if(!x&&!z) return 0;
if(!x) return -1;
ll m=(ll)ceil(sqrt((double)p)),tmp=1;
ma[1]=m+1;
for(int i=1;i<m;i++)
{
tmp=tmp*x%p;
if(!ma[tmp]) ma[tmp]=i;
}
ll inv=1;tmp=ksm(x,p-m-1,p);
for(ll k=0;k<m;k++)
{
int i=ma[(z*inv)%p];
if(i)
{
if(i==m+1) i=0;
return k*m+i;
}
inv=(inv*tmp)%p;
}
return -1;
}
字符串
AC自动机
struct AC
{
int ch[26];
int fail,cnt;
}a[500001];
int n,m,tot;
char s[1000001];
inline void init()
{
q.clear();
for(int i=0;i<=tot;i++)
{
memset(a[i].ch,0,sizeof(a[i].ch));
a[i].cnt=a[i].fail=0;
}
tot=0;
a[0].fail=-1;
}
inline void insert(char *s)
{
int now=0,p,len=strlen(s);
for(int i=0;i<len;i++)
{
p=s[i]-'a';
if(!a[now].ch[p]) a[now].ch[p]=++tot;
now=a[now].ch[p];
}
a[now].cnt++;
}
inline void makefail()
{
q.push(0);
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=0;i<26;i++)
if(a[now].ch[i])
{
int p=a[now].fail;
while(p!=-1&&!a[p].ch[i]) p=a[p].fail;
if(p==-1) a[a[now].ch[i]].fail=0;
else a[a[now].ch[i]].fail=a[p].ch[i];
q.push(a[now].ch[i]);
}
}
}
inline int find(int now)
{
int ans=0;
while(now&&a[now].cnt!=-1)
{
ans+=a[now].cnt;
a[now].cnt=-1;
now=a[now].fail;
}
return ans;
}
inline int ask(char *s)
{
int ans=0,now=0,len=strlen(s);
for(int i=0;i<len;i++)
{
int p=s[i]-'a';
if(a[now].ch[p]) now=a[now].ch[p];
else
{
int pos=a[now].fail;
while(pos!=-1&&!a[pos].ch[p]) pos=a[pos].fail;
if(pos==-1) now=0;
else now=a[pos].ch[p];
}
ans+=find(now);
}
return ans;
}
Fail树
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lowbit(x) x&(-x)
const int N=1e5+10;
struct AC
{
int ch[26];
int fail,fa;
}a[N];
struct query
{
int x,y,id;
bool operator <(const query other)const
{
return y<other.y;
}
}q[N];
struct edge
{
int next,to;
}e[N<<1];
int t[N],head[N],pos[N];
char s[N];
int in[N],out[N];
int ans[N];
int tot,num,n,x,y,Tot,len;
inline void add(int x,int y)
{
e[++num].next=head[x],e[num].to=y,head[x]=num;
e[++num].next=head[y],e[num].to=x,head[y]=num;
}
inline void build()
{
int now=0,num=0;
for(int i=0;i<len;i++)
if(s[i]=='B') now=a[now].fa;
else if(s[i]=='P') pos[++num]=now;
else
{
if(!a[now].ch[s[i]-'a']) a[now].ch[s[i]-'a']=++tot,a[a[now].ch[s[i]-'a']].fa=now;
now=a[now].ch[s[i]-'a'];
}
}
inline void makefail()
{
a[0].fail=-1;
queue<int>Q;
while(!Q.empty()) Q.pop();
for(int i=0;i<26;i++)
if(a[0].ch[i])
{
Q.push(a[0].ch[i]);
add(0,a[0].ch[i]);
}
while(!Q.empty())
{
int tmp=Q.front();Q.pop();
for(int i=0;i<26;i++)
{
if(!a[tmp].ch[i])
{
a[tmp].ch[i]=a[a[tmp].fail].ch[i];
continue;
}
a[a[tmp].ch[i]].fail=a[a[tmp].fail].ch[i];
add(a[a[tmp].fail].ch[i],a[tmp].ch[i]);
Q.push(a[tmp].ch[i]);
}
}
}
void dfs(int now,int fa)
{
in[now]=++Tot;
for(int i=head[now];i;i=e[i].next)
if(e[i].to!=fa) dfs(e[i].to,now);
out[now]=Tot;
}
inline void Add(int now,int num)
{
for(int i=now;i<=Tot;i+=lowbit(i))
t[i]+=num;
}
inline int ask(int now)
{
int ans=0;
for(int i=now;i;i-=lowbit(i))
ans+=t[i];
return ans;
}
inline void work()
{
int now=0,tot=0,j=1;
for(int i=0;i<len;i++)
if(s[i]>='a'&&s[i]<='z')
{
now=a[now].ch[s[i]-'a'];
Add(in[now],1);
}
else if(s[i]=='B')
{
Add(in[now],-1);
now=a[now].fa;
}
else
{
tot++;
for(;q[j].y==tot;j++)
ans[q[j].id]=ask(out[pos[q[j].x]])-ask(in[pos[q[j].x]]-1);
}
}
int main()
{
scanf("%s",s);
len=strlen(s);
build();
makefail();
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d %d",&q[i].x,&q[i].y),q[i].id=i;
sort(q+1,q+n+1);
dfs(0,-1);
work();
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}
后缀数组
inline void makesa()
{
int *x=t1,*y=t2,m=30;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[i]=s[i]-'a']++;
for(int i=1;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1)
{
int p=0;
for(int i=n-k;i<n;i++) y[p++]=i;
for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[y[i]]]++;
for(int i=1;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(int i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?p-1:p++;
if(p>=n) break;
m=p;
}
}
inline void makeheight()
{
for(int i=0;i<n;i++) rank[sa[i]]=i;
int k=0;
for(int i=0;i<n;i++)
if(rank[i])
{
int j=sa[rank[i]-1];
if(k) k--;
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
manacher
scanf("%d\n",&n);
a[0]='$';
for(int i=1;i<=n;i++)
a[++len]='#',a[++len]=getchar();
a[len+1]=a[len+2]='#';
for(int i=1;i<=len;i++)
{
if(i<mx) p[i]=min(p[pos*2-i],mx-i);
else p[i]=1;
while(a[i-p[i]]==a[i+p[i]]) p[i]++;
if(i+p[i]>mx) mx=i+p[i],pos=i;
}
for(int i=1;i<=len;i++)
if(a[i]=='#') f[i]=i;
else f[i]=i+1;
for(int i=3;i<=len;i+=2)
{
int tmp=i-(p[i]>>1);
if(!tmp) continue;
tmp=find(tmp);
while(tmp+p[tmp]<i&&tmp<i) f[tmp]=find(tmp+1),tmp=f[tmp];
if(tmp<i) ans=max(ans,(i-tmp)<<1);
}
KMP
scanf("%s%s",a+1,b+1);
l1=strlen(a+1),l2=strlen(b+1);
j=0;
for(i=2;i<=l2;i++)
{
while(j&&b[i]!=b[j+1]) j=next[j];
if(b[i]==b[j+1]) j++;
next[i]=j;
}
j=0;
for(i=1;i<=l1;i++)
{
while(j&&a[i]!=b[j+1]) j=next[j];
if(a[i]==b[j+1]) j++;
if(j==l2)
{
printf("%d\n",i-l2+1);
j=next[j];
}
}
数据结构
LCT
#include<bits/stdc++.h>
using namespace std;
struct node
{
int rev;
node *ch[2],*fa;
inline int getwh()
{
return fa->ch[0]==this?0:1;
}
inline void setch(int wh,node *child);
inline bool isroot();
inline void pushdown()
{
if(rev)
{
node *t=ch[0];ch[0]=ch[1];ch[1]=t;
ch[0]->rev^=1,ch[1]->rev^=1;
rev=0;
}
}
}pool[20001],*null;
inline void node::setch(int wh,node *child)
{
ch[wh]=child;
if(child!=null) child->fa=this;
}
inline bool node::isroot()
{
return (fa==null)||(fa->ch[0]!=this&&fa->ch[1]!=this);
}
char s[10];
int n,m,x,y;
inline void getstring()
{
int p=-1;char c=getchar();
while((c<'a'||c>'z')&&(c<'A'||c>'Z')) c=getchar();
while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) s[++p]=c,c=getchar();
}
inline void clear(node *now)
{
now->fa=now->ch[0]=now->ch[1]=null;
}
inline void rotate(node *now)
{
node *fa=now->fa,*grand=now->fa->fa;
if(!fa->isroot()) grand->pushdown();
fa->pushdown();now->pushdown();
int wh=now->getwh();
fa->setch(wh,now->ch[wh^1]);
if(fa->isroot()) now->fa=fa->fa;
else grand->setch(fa->getwh(),now);
now->setch(wh^1,fa);
}
inline void splay(node *now)
{
if(now->isroot()) return;
for(;!now->isroot();rotate(now))
if(!now->fa->isroot()) now->getwh()==now->fa->getwh()?rotate(now->fa):rotate(now);
}
inline node *access(node *now)
{
node *t=null;
for(;now!=null;t=now,now=now->fa)
splay(now),now->pushdown(),now->setch(1,t);
return t;
}
inline void changeroot(node *now)
{
access(now)->rev^=1;
splay(now);
}
inline void connect(node *x,node *y)
{
changeroot(x);
x->fa=y;
access(x);
}
inline void del(node *x,node *y)
{
changeroot(x);
access(y);
splay(x);
x->pushdown();
x->ch[1]=y->fa=null;
}
inline node *findroot(node *now)
{
for(now=access(now);now->ch[0]!=null;now->pushdown(),now=now->ch[0]);
return now;
}
inline bool ask(node *x,node *y)
{
if(findroot(x)==findroot(y)) return 1;
return 0;
}
int main()
{
null=pool;
null->fa=null->ch[0]=null->ch[1]=null;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
clear(pool+i);
while(m--)
{
getstring();
scanf("%d%d",&x,&y);
if(s[0]=='C') connect(pool+x,pool+y);
else if(s[0]=='D') del(pool+x,pool+y);
else if(s[0]=='Q') ask(pool+x,pool+y)?puts("Yes"):puts("No");
}
return 0;
}
splay
#include<cstdio>
const int INF=2000;
inline int max(int a,int b){if(a>=b)return a;return b;}
inline int min(int a,int b){if(a<=b)return a;return b;}
inline void swap(int &a,int &b){a^=b;b^=a;a^=b;}
struct stack
{
int t;
int a[500010];
inline void clear(){t=-1;}
inline void push(int &n){a[++t]=n;}
inline int top(){return a[t];}
inline void pop(){t--;}
inline bool empty(){return t<0;}
}reuse;
struct node
{
int num,size,lmax,rmax,maxn,sum,id,rev;
bool change;
node *ch[2],*fa;
inline void update()
{
size=ch[0]->size+ch[1]->size+1;
sum=ch[0]->sum+ch[1]->sum;
if(num!=-INF) sum+=num;
lmax=max(ch[0]->lmax,max(ch[0]->sum+num,ch[0]->sum+ch[1]->lmax+num));
rmax=max(ch[1]->rmax,max(ch[1]->sum+num,ch[1]->sum+ch[0]->rmax+num));
maxn=max(ch[0]->maxn,ch[1]->maxn);
maxn=max(maxn,max(ch[0]->rmax+num,ch[1]->lmax+num));
maxn=max(maxn,max(ch[0]->rmax+ch[1]->lmax+num,num));
}
inline int getwh()
{
if(fa->ch[0]==this) return 0;return 1;
}
inline void pushchange(int n)
{
num=n;
sum=size*n;
maxn=lmax=rmax=max(num,sum);
change=1;
}
inline void pushrev()
{
swap(lmax,rmax);
node *tmp=ch[0];ch[0]=ch[1];ch[1]=tmp;
rev^=1;
}
inline void setch(int wh,node *child);
inline void pushdown();
}pool[500010],*root,*null,*newroot;
inline void node::setch(int wh,node *child)
{
ch[wh]=child;
if(child!=null) child->fa=this;
update();
}
inline void node::pushdown()
{
if(rev)
{
if(ch[0]!=null) ch[0]->pushrev();
if(ch[1]!=null) ch[1]->pushrev();
rev=0;
}
if(change)
{
if(ch[0]!=null) ch[0]->pushchange(num);
if(ch[1]!=null) ch[1]->pushchange(num);
change=0;
}
}
char s[10];
int a[500010];
int n,m,tot,x,y,z;
inline void read(int &n)
{
n=0;char c=getchar();bool b=0;
while(c<'0'||c>'9'){if(c=='-')b=1;c=getchar();}
while(c>='0'&&c<='9') n=n*10+c-48,c=getchar();
if(b) n*=-1;
}
inline void getstring()
{
int p=-1;
char c=getchar();
while((c<'A'||c>'Z')&&c!='-') c=getchar();
while((c>='A'&&c<='Z')||c=='-') s[++p]=c,c=getchar();
}
inline node *getnew(int num)
{
node *now;
if(!reuse.empty()) now=pool+reuse.top(),now->id=reuse.top(),reuse.pop();
else now=pool+ ++tot,now->id=tot;
now->ch[0]=now->ch[1]=now->fa=null;
now->num=now->sum=now->maxn=now->lmax=now->rmax=num;
if(num==-1e9) now->sum=0;
now->size=1;
now->change=now->rev=0;
return now;
}
inline void rotate(node *now)
{
node *fa=now->fa,*grand=now->fa->fa;
int wh=now->getwh();
fa->setch(wh,now->ch[wh^1]);
now->setch(wh^1,fa);
now->fa=grand;
if(grand!=null)
{
if(grand->ch[0]==fa) grand->ch[0]=now;
else grand->ch[1]=now;
}
}
inline void splay(node *now,node *tar)
{
for(;now->fa!=tar;rotate(now))
if(now->fa->fa!=tar)
{
if(now->getwh()==now->fa->getwh()) rotate(now->fa);
else rotate(now);
}
if(tar==null) root=now;
}
node *build(int l,int r)
{
int mid=(l+r)>>1;
node *now=getnew(a[mid]);
if(l<mid) now->setch(0,build(l,mid-1));
if(r>mid) now->setch(1,build(mid+1,r));
return now;
}
inline node *kth(int rank)
{
node *now=root;
int ranking=0;
while(now!=null)
{
now->pushdown();
int tmp=ranking+now->ch[0]->size;
if(tmp+1==rank) return now;
if(tmp+1>rank) now=now->ch[0];
else ranking=tmp+1,now=now->ch[1];
}
}
inline void insert(node *newone,int pos)
{
splay(kth(pos),null);
splay(kth(pos+1),root);
root->ch[1]->setch(0,newone);
root->update();
}
void dfs(node *now)
{
reuse.push(now->id);
if(now->ch[0]!=null) dfs(now->ch[0]);
if(now->ch[1]!=null) dfs(now->ch[1]);
}
inline void del(int pos,int n)
{
splay(kth(pos-1),null);
splay(kth(pos+n),root);
dfs(root->ch[1]->ch[0]);
root->ch[1]->setch(0,null);
root->update();
}
inline void changenum(int pos,int n,int num)
{
splay(kth(pos-1),null);
splay(kth(pos+n),root);
root->ch[1]->ch[0]->pushchange(num);
root->ch[1]->update();
root->update();
}
inline void reverse(int pos,int n)
{
splay(kth(pos-1),null);
splay(kth(pos+n),root);
root->ch[1]->ch[0]->pushrev();
root->ch[1]->update();
root->update();
}
inline int sum(int pos,int n)
{
splay(kth(pos-1),null);
splay(kth(pos+n),root);
return root->ch[1]->ch[0]->sum;
}
int main()
{
read(n),read(m);
null=pool;
null->ch[0]=null->ch[1]=null->fa=null;
null->lmax=null->rmax=null->maxn=-INF;
root=null;
reuse.clear();
for(register int i=1;i<=n;i++)
read(a[i]);
a[0]=a[n+1]=-INF;
root=build(0,n+1);
while(m--)
{
getstring();
if(s[0]=='I')
{
read(x),read(y);
for(register int i=1;i<=y;i++)
read(a[i]);
newroot=build(1,y);
insert(newroot,x+1);
}
else if(s[0]=='D') read(x),read(y),del(x+1,y);
else if(s[2]=='K') read(x),read(y),read(z),changenum(x+1,y,z);
else if(s[0]=='R') read(x),read(y),reverse(x+1,y);
else if(s[0]=='G') read(x),read(y),printf("%d\n",sum(x+1,y));
else printf("%d\n",root->maxn);
}
return 0;
}
树链剖分
void dfs(int now,int fa,int depth)
{
deep[now]=depth;
f[now]=fa;
size[now]=1;
int tmp=-INF;
for(int i=head[now];i;i=a[i].next)
if(a[i].to!=fa)
{
dfs(a[i].to,now,depth+1);
size[now]+=size[a[i].to];
if(size[a[i].to]>tmp) tmp=size[a[i].to],son[now]=a[i].to;
}
}
void dfs2(int now,int high)
{
top[now]=high;
pos[now]=++tot;
num[tot]=s[now];
if(son[now]) dfs2(son[now],high);
for(int i=head[now];i;i=a[i].next)
if(a[i].to!=f[now]&&a[i].to!=son[now]) dfs2(a[i].to,a[i].to);
}
void addpath(int x,int y,int z)
{
int L,R;
if(top[x]==top[y])
{
L=min(pos[x],pos[y]);
R=max(pos[x],pos[y]);
return Add(L,R,1,n,1,z);
}
if(deep[top[x]]<deep[top[y]]) swap(x,y);
L=min(pos[x],pos[top[x]]);
R=max(pos[x],pos[top[x]]);
Add(L,R,1,n,1,z);
return addpath(y,f[top[x]],z);
}
inline int LCA(int x,int y)
{
while(top[x]!=top[y])
if(deep[top[x]]>deep[top[y]]) x=f[top[x]];
else y=f[top[y]];
return deep[x]<deep[y]?x:y;
}
inline int Ask(int x)
{
if(root==x) return t[1].num;
if(LCA(x,root)==x)
{
int ans=INF,from;
for(int i=head[x];i;i=a[i].next)
if(LCA(a[i].to,root)==a[i].to){from=a[i].to;break;}
if(pos[from]>1) ans=min(ans,ask(1,pos[from]-1,1,n,1));
if(pos[from]+size[from]<=n) ans=min(ans,ask(pos[from]+size[from],n,1,n,1));
return ans;
}
return ask(pos[x],pos[x]+size[x]-1,1,n,1);
}
计算几何
//凸包
const double eps=1e-10;
struct point
{
double x,y;
point(){}
point(double xx,double yy):x(xx),y(yy){}
inline point operator -(const point other)const
{
return point(x-other.x,y-other.y);
}
inline bool operator <(const point other)const
{
if(x==other.x) return y<other.y;
return x<other.x;
}
}a[10005],s[10005];
int n,top;
double ans;
inline int dcmp(double a,double b)
{
if(fabs(a-b)<eps) return 0;
return a>b?1:-1;
}
inline double cross(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
inline void solve()
{
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
while(top>1&&dcmp(cross(s[top]-s[top-1],a[i]-s[top-1]),0)<=0) top--;
s[++top]=a[i];
}
int num=top;
for(int i=n-1;i;i--)
{
while(top>num&&dcmp(cross(s[top]-s[top-1],a[i]-s[top-1]),0)<=0) top--;
s[++top]=a[i];
}
}
//半平面交
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const double INF=1e100;
const double eps=1e-10;
const int N=305;
struct point
{
double x,y;
point(){}
point(double xx,double yy):x(xx),y(yy){}
inline point operator +(const point other)const
{
return point(x+other.x,y+other.y);
}
inline point operator -(const point other)const
{
return point(x-other.x,y-other.y);
}
inline point operator *(const double other)const
{
return point(x*other,y*other);
}
};
inline int dcmp(double a,double b)
{
if(fabs(a-b)<eps) return 0;
return a>b?1:-1;
}
inline double cross(point a,point b)
{
return a.x*b.y-b.x*a.y;
}
inline double supercross(point a,point b,point c)
{
return cross(point(b.x-a.x,b.y-a.y),point(c.x-b.x,c.y-b.y));
}
struct line
{
point s,v;
line(){}
line(point ss,point vv):s(ss),v(vv){}
inline bool operator <(const line other)const
{
double rate1=atan2(v.y,v.x),rate2=atan2(other.v.y,other.v.x);
if(!dcmp(rate1,rate2)) return dcmp(supercross(s,s+v,other.s),0)==-1;
else return rate1<rate2;
}
};
inline point inter(line a,line b)
{
point u=b.s-a.s;
double rate=cross(u,b.v)/cross(a.v,b.v);
return a.s+(a.v*rate);
}
inline bool onleft(line a,point p)
{
return dcmp(supercross(a.s,a.s+a.v,p),0)>0;
}
inline double high(point a,point b,double p)
{
return inter(line(a,b-a),line(point(p,0),point(0,1))).y;
}
struct halfinter
{
line a[N],q[N];
int n,h,t;
point tmp[N];
inline void solve()
{
sort(a+1,a+n+1);
q[h=t=1]=a[1];
for(int i=2;i<=n;i++)
{
if(!cross(a[i].v,a[i-1].v)) continue;
while(h<t&&!onleft(a[i],inter(q[t-1],q[t]))) t--;
while(h<t&&!onleft(a[i],inter(q[h],q[h+1]))) h++;
q[++t]=a[i];
}
while(h+1<t&&!onleft(q[h],inter(q[t],q[t-1]))) t--;
while(h+1<t&&!onleft(q[t],inter(q[h],q[h+1]))) h++;
for(int i=h;i<t;i++)
tmp[i]=inter(q[i],q[i+1]);
}
}half;
int x[N],y[N];
int n;
double ans=INF;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&x[i]);
for(int i=1;i<=n;i++)
scanf("%d",&y[i]);
for(int i=1;i<n;i++)
half.a[i]=line(point(x[i],y[i]),point(x[i+1]-x[i],y[i+1]-y[i]));
half.n=n+1;
half.a[n]=line(point(x[1],0),point(0,-1));
half.a[n+1]=line(point(x[n],0),point(0,1));
half.solve();
for(int i=half.h,j=1;i<=half.t;i++)
{
while(dcmp(x[j],half.tmp[i].x)>0||dcmp(half.tmp[i].x,x[j+1])>0) j++;
ans=min(ans,half.tmp[i].y-high(point(x[j],y[j]),point(x[j+1],y[j+1]),half.tmp[i].x));
}
for(int i=1,j=half.h;i<=n;i++)
{
while(dcmp(half.tmp[j].x,x[i])>0||dcmp(x[i],half.tmp[j+1].x)>0) j++;
ans=min(ans,high(half.tmp[j],half.tmp[j+1],x[i])-y[i]);
}
printf("%.3lf",ans);
return 0;
}