[洛谷P3932]浮游大陆的68号岛
Posted Mrsrz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[洛谷P3932]浮游大陆的68号岛相关的知识,希望对你有一定的参考价值。
题目大意:有一行物品,每两个物品之间有一个距离。每个物品有一个价值。现在问你若干问题,每个问题问你把l~r所有物品全部搬到物品x处需要多少价值。
把物品a搬到物品b处的价值为物品a的价值乘a到b的距离。
解题思路:前缀和。
首先我们考虑$x<l<r$的情况。
发现答案为$\sum\limits ^{r}_{i=l} a[i]×dis(x,i)$。其中a[i]是第i个物品的价值,dis(x,i)表示x到i的距离。
首先我们容易想到用前缀和保存距离,即$dis[i]=\sum\limits^r _{i=2}p[i]$。p[i]表示i到i-1的距离。
但时间复杂度仍然很高,怎么办?
我们可以再用一个前缀和,用ds[i]保存第1到i个物品,每个物品到第一个物品的价值总和,即$ds[i]=\sum\limits^r_i=1 a[i]×dis[i]$。
那么ds[r]-ds[l-1]就表示l到r所有物品搬到1的价值,可是要求的是到x的距离,怎么办?
我们发现,这个答案多出来的其实是l到r所有物品搬dis[x]距离的价值,即多搬了1到x的距离。
那么就在答案中减去$\sum\limits^r _{i=l} a[i]×dis[x]=(\sum\limits^r_{i=l}a[i])×dis[x]$。
发现a[i]也可以用前缀和,那么我们令$sum[i]=\sum\limits^r _{i=1} a[i]$。
那么最后答案为$ds[r]-sd[l-1]+dis[x]×(sum[r]-sum[l-1])$。
当$l<r<x$时,可以用后缀和,然后求解即可。
当$l\leq x\leq r$时,我们把它分成两段,l~x-1和x+1~r,分别求解即可。
由于求解时间复杂度$O(1)$,求前缀和时间复杂度$O(n)$,所以总时间复杂度$O(n+m)$,在洛谷神机+O2下时间完全不是问题。
注意边算边模和long long(数组也要,不然答案就会莫名其妙地错误)。
C++ Code:
#include<cstdio> #include<cctype> using namespace std; #define mod 19260817 #define N 200020 int n,m,a[N]; long long disl[N],disr[N],dsl[N],dsr[N],suml[N],sumr[N]; inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^‘0‘); return d; } inline long long ansL(int l,int r,int x){return((dsl[r]-dsl[l-1]+mod)%mod-(long long)disl[x]*((suml[r]-suml[l-1]+mod)%mod)%mod+mod)%mod;} inline long long ansR(int l,int r,int x){return((dsr[l]-dsr[r+1]+mod)%mod-(long long)disr[x]*((sumr[l]-sumr[r+1]+mod)%mod)%mod+mod)%mod;} int main(){ n=readint(); m=readint(); disl[1]=disr[n]=suml[0]=sumr[n+1]=0; for(int i=2;i<=n;++i)disl[i]=(disl[i-1]+(a[i]=readint()%mod))%mod; for(int i=n;i>1;--i)disr[i-1]=(disr[i]+a[i])%mod; for(int i=1;i<=n;++i)suml[i]=(suml[i-1]+(a[i]=readint()%mod))%mod; for(int i=n+1;i;--i)sumr[i]=(sumr[i+1]+a[i])%mod; dsl[0]=dsr[n+1]=0; for(int i=1;i<=n;++i) dsl[i]=(dsl[i-1]+disl[i]*a[i]%mod)%mod; for(int i=n;i;--i) dsr[i]=(dsr[i+1]+disr[i]*a[i]%mod)%mod; while(m--){ int x=readint(),l=readint(),r=readint(); if(l>r)l^=r^=l^=r; if(x<l)printf("%d\n",(int)ansL(l,r,x));else if(x>r)printf("%d\n",(int)ansR(l,r,x));else printf("%d\n",(int)((ansR(l,x-1,x)+ansL(x+1,r,x))%mod)); } return 0; }
以上是关于[洛谷P3932]浮游大陆的68号岛的主要内容,如果未能解决你的问题,请参考以下文章