[COGS 2264]魔法传输

[COGS 2264]魔法传输

题目

自从看了《哈利波特》,小Y就十分渴望获得魔法值。于是他和一群向往魔法的孩子(当然这些孩子们都是不会魔法的)来到了哈利波特的家,大家坐成一排。哈利波特会不时的给大家传输魔法。

哈利每次会选择一个区间,给这个区间里的孩子们传输魔法:最左边的孩子给一点,第二个给两点……哈利有时会突然问你某一个孩子已经有了多少魔法。

INPUT

第一行两个正整数 N,M,表示有 N 个孩子,哈利有 M 次操作。

接下来 M 行,每行代表一个操作。第一个字符为 ci,若 ci=‘C’则此次操作为传送魔法操作,接下来会有两个整数Li,Ri,表示此次送魔法值的区间。若 ci=‘Q’则此次操作为询问操作,接下来一个整数xi,表示询问第xi个孩子当前的魔法值。

OUTPUT

对于每组询问输出一行,仅包含一个整数,表示答案对 1,000,000,007 取模(mod)的结果。

SAMPLE

INPUT

3 4

C 1 3

Q 2

C 2 3

Q 2

OUTPUT

2

3

数据规模

对于 30%的数据,N,M≤1,000;

对于 100%的数据,N,M≤100,000。

解题报告

一道难得的好题= =

实际上这道题除了想出思路,哪都很容易= =

这道题的主要难度就在于如何更改上,等差数列更改让一些数据结构显得很吃力,但实则不然,我们完全可以用线段树来实现这个东西

我们首先思考,在线段树中如何更新。

我们发现,我们需要在一段区间更新一段以$1$为首项的等差数列,那么,我们假如只在区间的每一个点加$1$,效果会怎样?

显然这时候如果单点求和是不行的,但如果我们求前缀和的话,我们就可以得到等差数列求和的效果了不是吗?

所以,我们可以看出,这是一道在线段树上的差分题。

我们只需要在区间中的每一个点都加上$1$,右端点右面一个点减去$r-l+1$就可以达到差分的目的,查询时只需要查询单点前缀和即可

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 inline int read(){
 6     int sum(0);
 7     char ch(getchar());
 8     for(;ch<'0'||ch>'9';ch=getchar());
 9     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
10     return sum;
11 }
12 typedef long long L;
13 int n,m;
14 L sum[400005],add[400005];
15 const L mod=1000000007;
16 inline void pushup(int i){
17     sum[i]=(sum[i<<1]+sum[i<<1|1])%mod;
18 }
19 inline void pushdown(int i,int len){
20     if(add[i]){
21         add[i<<1]+=add[i];
22         add[i<<1|1]+=add[i];
23         sum[i<<1]+=add[i]*(len-(len>>1));
24         sum[i<<1]%=mod;
25         sum[i<<1|1]+=add[i]*(len>>1);
26         sum[i<<1|1]%=mod;
27         add[i]=0;
28     }
29 }
30 inline void update(int ll,int rr,L w,int l,int r,int i){
31     if(ll<=l&&r<=rr){
32         add[i]+=w;
33         sum[i]+=w*(L)(r-l+1);
34         sum[i]%=mod;
35         return;
36     }
37     pushdown(i,r-l+1);
38     int mid((l+r)>>1);
39     if(ll<=mid)
40         update(ll,rr,w,l,mid,i<<1);
41     if(mid<rr)
42         update(ll,rr,w,mid+1,r,i<<1|1);
43     pushup(i);
44 }
45 inline L query(int ll,int rr,int l,int r,int i){
46     if(ll<=l&&r<=rr)
47         return sum[i];
48     pushdown(i,r-l+1);
49     L ret(0);
50     int mid((l+r)>>1);
51     if(ll<=mid)
52         ret=(ret+query(ll,rr,l,mid,i<<1))%mod;
53     if(mid<rr)
54         ret=(ret+query(ll,rr,mid+1,r,i<<1|1))%mod;
55     return ret;
56 }
57 char op[2];
58 inline int gg(){
59     freopen("magics.in","r",stdin);
60     freopen("magics.out","w",stdout);
61     n=read(),m=read();
62     while(m--){
63         scanf("%s",op);
64         if(op[0]=='Q'){
65             int x(read());
66             printf("%lld
",query(1,x,1,n,1)%mod);
67         }
68         else{
69             int x(read()),y(read());
70             update(x,y,1,1,n,1);
71             update(y+1,y+1,-(y-x+1),1,n,1);
72         }
73     }
74     return 0;
75 }
76 int K(gg());
77 int main(){;}
View Code
原文地址:https://www.cnblogs.com/hzoi-mafia/p/7358997.html