[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\n",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(){;}