板子

基本

快读

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;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值