未写完

扫码查看

code:

#include <map>
#include <string>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define N 300007
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
ll ans;
int rt[N<<1],ar[N],del[N],n,st,ed,length;
namespace seg
{
    int tot;
    struct node { int l,r,sum; }s[N*50];
    void update(int &x,int l,int r,int p,int v)
    {
        if(!x) x=++tot;
        ++s[x].sum;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(p<=mid) update(s[x].l,l,mid,p,v);
        else update(s[x].r,mid+1,r,p,v);
    }
    int query(int x,int l,int r,int L,int R)
    {
        if(l>=L&&r<=R) return s[x].sum;
        int mid=(l+r)>>1,re=0;
        if(L<=mid) re+=query(s[x].l,l,mid,L,R);
        if(R>mid)  re+=query(s[x].r,mid+1,r,L,R);
        return re;
    }
    int merge(int x,int y)
    {
        if(!x||!y) return x+y;
        int now=++tot;
        s[now].sum=s[x].sum+s[y].sum;
        s[now].l=merge(s[x].l,s[y].l);
        s[now].r=merge(s[x].r,s[y].r);
        return now;
    }
    ll queryr(int x,int l,int r,int L,int R)
    {
        if(!x||L>R) return 0;
        if(l>=L&&r<=R) return (ll)s[x].sum*max(0,min(l-st+1,length));
        int mid=(l+r)>>1;  ll re=0ll;
        if(L<=mid)  re+=queryr(s[x].l,l,mid,L,R);
        if(R>mid)   re+=queryr(s[x].r,mid+1,r,L,R);
        return re;
    }
    ll queryl(int x,int l,int r,int L,int R)
    {
        if(!x||L>R) return 0;
        if(l>=L&&r<=R) return (ll)s[x].sum*max(0,min(ed-r+1,length));
        int mid=(l+r)>>1;  ll re=0ll;
        if(L<=mid)  re+=queryl(s[x].l,l,mid,L,R);
        if(R>mid)   re+=queryl(s[x].r,mid+1,r,L,R);
        return re;
    }
};
namespace sam
{
    int last,tot;
    map<int,int>ch[N<<1];
    int mx[N<<1],pre[N<<1],A[N<<1],rk[N<<1],pos[N<<1];
    void init() { last=tot=1; }
    struct node
    {
        int x,id;
        node(int x=0,int id=0):x(x),id(id){}
    };
    vector<node>G[N<<1];
    void extend(int c,int i)
    {
        int np=++tot,p=last;
        mx[np]=mx[p]+1,last=np;
        for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;
        if(!p) pre[np]=1;
        else
        {
            int q=ch[p][c];
            if(mx[q]==mx[p]+1) pre[np]=q;
            else
            {
                int nq=++tot;
                mx[nq]=mx[p]+1;
                ch[nq]=ch[q];
                pre[nq]=pre[q],pre[q]=pre[np]=nq;
                for(;p&&ch[p][c]==q;p=pre[p]) ch[p][c]=nq;
            }
        }
        seg::update(rt[np],1,n,i,1);
        G[np].push_back(node(i,rt[np]));
    }
    void solve()
    {
        int i,j;
        for(i=1;i<=tot;++i) ++A[mx[i]],pos[i]=i;
        for(i=1;i<=tot;++i) A[i]+=A[i-1];
        for(i=1;i<=tot;++i) rk[A[mx[i]]--]=i;
        for(i=tot;i>1;--i)
        {
            int u=rk[i];
            int ff=pre[u];
            if(ff==1) continue;
            int rt1=rt[u],rt2=rt[ff];
            if(G[pos[u]].size()>G[pos[ff]].size()) swap(pos[u],pos[ff]),swap(rt1,rt2);
            printf("1 :: ");
            for(j=0;j<G[pos[ff]].size();++j)  printf(" %d",G[pos[ff]][j]);
            printf("\n");
            printf("2 :: ");
            for(j=0;j<G[pos[u]].size();++j)
            {
                printf(" %d",G[pos[u]][j]);
                node e=G[pos[u]][j];
                length=mx[ff];
                st=e.x+1;
                ed=e.x-1;
                ll tp=ans;
                ans+=seg::queryr(rt2,1,n,st,n);
                ans+=seg::queryl(rt2,1,n,1,ed);
                G[pos[ff]].push_back(G[pos[u]][j]);
            }
            printf("\n");
            rt[ff]=seg::merge(rt[ff],rt[u]);
        }
    }
};
int main()
{
    int i,j;
    setIO("input");
    sam::init(),scanf("%d",&n),ans=(ll)n*(n-1)/2;
    for(i=1;i<=n;++i) scanf("%d",&ar[i]);
    for(i=1;i<n;++i)  del[i]=ar[i+1]-ar[i];
    --n;
    for(i=1;i<=n;++i) sam::extend(del[i],i);
    sam::solve();
    printf("%lld\n",ans);
    return 0;
}

  

12-14 13:58
查看更多