首页 > 其他分享 >题解 WD与数列

题解 WD与数列

时间:2024-01-19 15:13:48浏览次数:29  
标签:rt WD 数列 int 题解 sum second maxn res

P5161 WD与数列

可以想到原条件是一个差分形式,所以我们对原数组差分。然后发现答案其实就是 \(\sum_{i<j} \min(lcp(i+1,j+1)+1,j-i)\)。

这个东西先跑 SA,然后建笛卡尔树。

考虑对于一个区间,其值为 \(x\)。那么相当于是求 \(\sum_{l\in S,r\in T} \min(|sa_{l}-sa_{r}|,x)\)。

笛卡尔树的一个性质是:较小的区间之和不超过 \(O(n\log n)\)。所以直接暴力枚举较小区间,假设为 \(l\),那么对于右边相当于是求区间内 \(\le\) 某个数的个数,我们显然可以把询问按照 \(x\) 离线下来,从小到大做。或者直接开主席树,都是 \(O(n\log^2n)\) 的。这题略微卡常,注意实现

  • 好像存在 \(O(n\log n)\) 的做法。
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxt=1e7, maxn=3e5+5;

int n,m;
int sa[maxn], rk[maxn], cnt[maxn], tp[maxn], height[maxn], lg[maxn], w[maxn][20];
int s[maxn], a[maxn];

void basesort(){
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++) cnt[rk[i]]++;
    for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1]; 
    for(int i=n;i>=1;i--) sa[cnt[rk[tp[i]]]--]=tp[i];
    return ;
}

void SuffixSort() {
    for(int i=1;i<=n;i++) rk[i]=s[i],tp[i]=i;
    basesort();
    for(int w=1,p=0;p<n;m=p,w<<=1) {
        p=0;
        for(int i=1;i<=w;i++) tp[++p]=n-w+i;
        for(int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
        basesort();
        for(int i=1;i<=n;++i) swap(tp[i],rk[i]);
        rk[sa[1]]=1; 
		p=1;
        for(int i=2;i<=n;i++) {
        	if(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w]) rk[sa[i]]=p;
            else rk[sa[i]]=++p;
        }
    }
    return ;
}

int lcp(int l,int r) {
    int k=lg[r-l];
    return min(w[l+1][k],w[r-(1<<k)+1][k]);
}

void init() {
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) s[i]=a[i]-a[i-1];
    for(int i=1;i<=n;i++) a[i]=s[i];
    sort(a+1,a+n+1); m=unique(a+1,a+n+1)-a-1;
    for(int i=1;i<=n;i++) s[i]=lower_bound(a+1,a+m+1,s[i])-a;
    SuffixSort();
    int k=0;
    for(int i=1;i<=n;i++) {
        if(k) --k;
        int j=sa[rk[i]-1];
        while(i+k<=n&&s[i+k]==s[j+k]) ++k;
        height[rk[i]]=k;
    }
    lg[1]=0;
    for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
    for(int i=1;i<=n;i++) w[i][0]=height[i];
    for(int j=1;(1<<j)<=n;j++) {
        for(int i=1;i+(1<<j)-1<=n;i++) {
            w[i][j]=min(w[i][j-1],w[i+(1<<j-1)][j-1]);
        }
    }
    return ;
}

int tl[maxn], tr[maxn];

int tot;
int ls[maxt], rs[maxt], rt[maxn];
ll sum[maxt], sum2[maxt];

void build(int &x,int l,int r) {
    x=++tot;
    if(l==r) return ;
    int mid=l+r>>1;
    build(ls[x],l,mid);
    build(rs[x],mid+1,r);
    return ;
}

void updata(int &x,int x2,int p,int c,int l,int r) {
    x=++tot;
    sum[x]=sum[x2]+p*c, sum2[x]=sum2[x2]+c, ls[x]=ls[x2], rs[x]=rs[x2];
    if(l==r) return ;
    int mid=l+r>>1;
    if(p<=mid) updata(ls[x],ls[x2],p,c,l,mid);
    else updata(rs[x],rs[x2],p,c,mid+1,r);
    return ;
}

pair<ll,ll> operator + (pair<ll,ll> x,pair<ll,ll> y) {
    return {x.first+y.first,x.second+y.second};
}

pair<ll,ll> query(int x1,int x2,int L,int R,int l,int r) {
    if(L>R) return {0,0};
    if(L<=l&&r<=R) return {sum[x2]-sum[x1],sum2[x2]-sum2[x1]};
    int mid=l+r>>1;
    pair<ll,ll> res={0,0};
    if(L<=mid) res=res+query(ls[x1],ls[x2],L,R,l,mid);
    if(mid<R) res=res+query(rs[x1],rs[x2],L,R,mid+1,r);
    return res;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    init();
    vector<int> vec;
    for(int i=2;i<=n;i++) {
        while(vec.size()&&height[vec.back()]>=height[i]) {
            tr[vec.back()]=i;
            vec.pop_back();
        }
        if(vec.size()) tl[i]=vec.back();
        else tl[i]=1;
        vec.push_back(i);
    }
    while(vec.size()) tr[vec.back()]=n+1, vec.pop_back();
    build(rt[0],1,n);
    for(int i=1;i<=n;i++) updata(rt[i],rt[i-1],sa[i],(sa[i]!=1),1,n);
    ll ans=0;
    for(int i=2;i<=n;i++) {
        int l=tl[i], r=tr[i]; --r;
        int x=height[i]+1;
        if(i-l<=r-i+1) {
            for(int j=l;j<i;j++) {
                int v=sa[j];
                if(v==1) continue;
                ll sum=r-i+1-(i<=rk[1]&&rk[1]<=r);
                pair<ll,ll> res=query(rt[i-1],rt[r],max(v-x,1),v,1,n);
                ans+=res.second*v-res.first, sum-=res.second;
                res=query(rt[i-1],rt[r],v+1,min(v+x,n),1,n);
                ans+=res.first-res.second*v, sum-=res.second;
                ans+=sum*x;
            }
        }else {
            for(int j=i;j<=r;j++) {
                int v=sa[j];
                if(v==1) continue;
                ll sum=i-l-(l<=rk[1]&&rk[1]<i);
                pair<ll,ll> res=query(rt[l-1],rt[i-1],max(v-x,1),v,1,n);
                ans+=res.second*v-res.first, sum-=res.second;
                res=query(rt[l-1],rt[i-1],v+1,min(v+x,n),1,n);
                ans+=res.first-res.second*v, sum-=res.second;
                ans+=sum*x;
            }
        }
    }
    cout<<ans+n-1<<'\n';
    return 0;
}

标签:rt,WD,数列,int,题解,sum,second,maxn,res
From: https://www.cnblogs.com/OIshima/p/17974642

相关文章

  • AT_arc115_b [ARC115B] Plus Matrix 题解
    AT_arc115_b[ARC115B]PlusMatrix题解题意给定矩阵\(C_{n\timesn}\),求两个数列\(A_n,B_n\),使得\(C_{i,j}=A_i+B_j\)。分析画出一个表格来:213243502131324可以看出来,对于任意一列\(j\),\(C_{*,j}\)都存在有\(B_j\)的贡献。那么我们......
  • ELK之Filebeat自动断开问题解决
     自动断开命令 解决自动断开命令nohup./filebeat-e-cfilebeat.yml>./filebeat.log 2>&1& disown 其他的方式(目前我没有使用) 在linux操作系统/etc/systemd/system目录下创建一个filebeat.service文件,写入如下内容需要注意替换文件的位置以及版本[Unit]D......
  • GDKOI 2024 题解
    鸽了一些题。匹配先抽出来一个完美匹配,然后尝试调整。调整相当于:找一个偶环,满足匹配的边和未匹配的边交错,且偶环的总异或和为\(0\),是不是写个暴力就好了?发现冲过去了,很牛逼,复杂度\(O(n^3)\)(?),Code。不休陀螺一个区间可以被打出的条件是:令\(\Delta_i=b_i-a_i\),则\(x=\sum......
  • P2580 于是他错误的点名开始了题解
    “普及/提高-”这个难度很有意思。说明这题可能需要用到提高组当中比较基础的内容。它的名字叫做map。map,其实相当于一个超大数组,但它真实的作用是:映射。比如a[7]=5;就是用a数组把7和5关联了起来,这个操作就叫映射。map这东西NB的地方在于,它能这么写:score["Leo201......
  • P9012 [USACO23JAN] Moo Operations B题解
    第1道赛场AC的题,必须发篇题解记录一下。Tips:\(1\le|S|\le100\)——题目才100,这就可以随便整活了。如果你稍微懂点英语,就会知道第\(2\sim4\)个点的\(S\)都最多只有\(3\)个字符,而目标“MOO”也是\(3\)个字符,所以只需要模拟就可以了。intcheck(string......
  • [GFCTF 2021]web部分题解(更新中ing)
    [GFCTF2021]Baby_Web拿源码环节:打开环境(◡ᴗ◡✿)乍一看什么都没有,F12下没看到js文件,但是看到了出题师傅的提示:“源码藏在上层目录xxx.php.txt里面,但你怎么才能看到它呢?”这时候在思考文件在上层目录中,既然是目录下那就试一下dirsearch扫描先看看后台都有什么(这里就直接......
  • Dojoup 安装问题解决
    Dojoup安装问题解决InstallDojouphttps://book.dojoengine.org/getting-started/quick-start.htmlcurl-Lhttps://install.dojoengine.org|bash安装失败dojoup═══════════════════════════════════════════════......
  • Oozie重试任务不生效问题解决
    1、oozie默认为不重试规则,想要重试需在action中配置重试规则,示例如下:retry-max="3"retry-interval="1"发现增加以上配置后,任务失败并未生效;2、在~/oozie/conf/oozie-site.xml中增加以下配置:<property><name>oozie.service.LiteWorkflowStoreService.user.retry.error.cod......
  • [AGC044E] Random Pawn题解
    [AGC044E]RandomPawn题解题目链接AtCoder原题链接Step1.拆环原问题是在环上的问题,考虑将环拆开变成链来处理。因此,我们需要找到一个点,使得操作越过这个点一定不优。令使\(a\)的值最大的位置的下标为\(maxp\)。容易发现,如果现在正处在\(maxp\)上,那么继续操作一定不可......
  • 题解 CF741E Arpa’s abnormal DNA and Mehrdad’s deep interest
    CF741EArpa’sabnormalDNAandMehrdad’sdeepinterest记\(R_{i}\)表示把\(T\)插入在\(S\)的第\(i\)位后组成的字符串。有\(q\)组询问,给定\((x,y,l,r)\),求\(\min_{i}R_{i},({i\in[l,r],i\%k\in[x,y]})\)。一个暴力的想法是先把\(R_{i}\)的排名求出来,这显......