有一天小妖精们又在做游戏。这个游戏是这样的。
妖精仓库的储物点可以看做在一个数轴上。每一个储物点会有一些东西,同时他们之间存在距离。
每次他们会选出一个小妖精,然后剩下的人找到区间[l,r][l,r]储物点的所有东西,清点完毕之后问她,把这个区间内所有储物点的东西运到另外一个仓库的代价是多少?
比如储物点ii有xx个东西,要运到储物点jj,代价为
x * dis( i , j )
dist就是仓库间的距离。
当然啦,由于小妖精们不会算很大的数字,因此您的答案需要对19260817取模。
输入输出格式
输入格式:
第一行两个数表示n,mn,m
第二行n-1n−1个数,第ii个数表示第ii个储物点与第i+1i+1个储物点的距离
第三行nn个数,表示每个储物点的东西个数
之后mm行每行三个数x l r
表示查询要把区间[l,r][l,r]储物点的物品全部运到储物点x的花费
输出格式:
对于每个询问输出一个数表示答案
输入输出样例
输入样例#1:
5 5
2 3 4 5
1 2 3 4 5
1 1 5
3 1 5
2 3 3
3 3 3
1 5 5
输出样例#1:
125
72
9
0
70
说明
对于30%的数据,n , m \le 1000n,m≤1000
对于另外20%的数据,所有储物点间的距离都为1
对于另外20%的数据,所有储物点的物品数都为1
对于100%的数据 , n , m <= 200000 ;n,m≤200000;ai,bi<=2⋅10^9
具体解法见题解这里记录一些错误与注意事项
bzoi LittlePrincess十分喜爱安利树状数组,众所周知。
然后这道题的数据范围是20w 很自然想到nlogn复杂度哇,加之本蒟蒻喜爱安利树状数组,然后就写了个树状数组。。写完发现不用动态QAQ。。
①静态题不要想bit数组!
②不要被数据范围蒙蔽!
/*
(a + b) mod n = ((a mod n) + (b mod n)) mod n
(a - b) mod n = ((a mod n) - (b mod n) + n) mod n
(a * b) mod n = ((a mod n) * (b mod n)) mod n
对于除法没有类似公式,但是可以通过求逆元的方法,转换成乘法运算求模(见下面)
*/
取膜一定要按照法则,不要yy,更不要xjb模
下面是很沙茶的bit数组代码
#include
using namespace std;
#define lb(x) x&-x
#define LL long long
#define MN 200010
int n,m,ll,rr,dis[MN],dep[MN],c1[MN],c2[MN],a[MN],x,p=19260817;
void ad2(int x,int pos)
{
for(;pos<=n;pos+=lb(pos)) c2[pos]+=x,c2[pos]%=p;
}
void ad1(int x,int pos)
{
for(;pos<=n;pos+=lb(pos)) c1[pos]+=x,c1[pos]%=p;
}
int gsum1(int pos)
{
int ans=0;
for(;pos;pos-=lb(pos)) {ans+=c1[pos],ans%=p;}
return ans;
}
int gsum2(int pos)
{
int ans=0;
for(;pos;pos-=lb(pos)) {ans+=c2[pos],ans%=p;}
return ans;
}
int work(int l,int r,int k,int x)
{
if(l>r) return 0;int ans=0;
int wor=(((gsum2(r)-gsum2(l-1))%p+p)%p);
int rwz=((gsum1(r)-gsum1(l-1))%p+p)%p;
int xgz=((dis[x]%p)*(((gsum2(r)-gsum2(l-1))%p+p)%p))%p;
if(k==-1)
ans=((rwz-xgz)%p);
else ans=((xgz-rwz+p)%p)%p;
return ans;
}
int main()
{
//freopen("sample4.in","r",stdin);
//freopen("a.txt","w",stdout);
cin>>n>>m;
for(int i=2,_;i<=n;i++)
{cin>>_;dis[i]=(dis[i-1]+_)%p;}
for(int i=1;i<=n;i++){cin>>a[i];a[i]%=p;ad2(a[i],i);}
for(int i=1;i<=n;i++)
dep[i]=(((dis[i]%p)*(a[i]%p))%p+p)%p,ad1(dep[i],i);
while(m--)
{
cin>>x>>ll>>rr;
if(x>rr) cout<1,x)<else if(x1,x)<else cout<<(work(ll,x-1,1,x)+work(x+1,rr,-1,x))%p<
下面是ac代码
#include
using namespace std;
#define LL long long
#define MN 200010
int n,m,ll,rr,dis[MN],sum1[MN],sum2[MN],a[MN],x,p=19260817;
int work(int l,int r,int k,int x)
{
if(l>r) return 0;
return
k==-1?((sum1[r]-sum1[l-1]+p)%p-((LL)dis[x]*((sum2[r]-sum2[l-1]+p)%p))%p+p)%p
:(((LL)dis[x]*((sum2[r]-sum2[l-1]+p)%p))%p-(sum1[r]-sum1[l-1]+p)%p+p)%p;
}
int main()
{
// freopen("sample3.in","r",stdin);
// freopen("a.txt","w",stdout);
cin>>n>>m;for(int i=2,_;i<=n;i++)
cin>>_,dis[i]=(dis[i-1]+_)%p;//sum1[i]=(sum1[i-1]+dis[i])%p;
for(int i=1;i<=n;i++)
cin>>a[i],a[i]%=p,sum2[i]=(sum2[i-1]+a[i])%p,sum1[i]=(sum1[i-1]+((LL)a[i]*dis[i])%p)%p;
// for(int i=1;i<=n;i++) if(sum2[i]<0||dis[i]<0||a[i]<0) cout<<" swdwd";
while(m--)
{
cin>>x>>ll>>rr;
if(x>rr) cout<1,x)<else if(x1,x)<else cout<<(work(ll,x-1,1,x)+work(x+1,rr,-1,x))%p<return 0;
}