洛谷八连测——关于取模与思维僵化

有一天小妖精们又在做游戏。这个游戏是这样的。

妖精仓库的储物点可以看做在一个数轴上。每一个储物点会有一些东西,同时他们之间存在距离。

每次他们会选出一个小妖精,然后剩下的人找到区间[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


洛谷月赛题

具体解法见题解这里记录一些错误与注意事项

1 思维僵化

bzoi LittlePrincess十分喜爱安利树状数组,众所周知。
然后这道题的数据范围是20w 很自然想到nlogn复杂度哇,加之本蒟蒻喜爱安利树状数组,然后就写了个树状数组。。写完发现不用动态QAQ。。

①静态题不要想bit数组!
②不要被数据范围蒙蔽!

2 模法

/* 
    (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;
}

你可能感兴趣的:(沙茶)