种西瓜
Time Limit: 1000 ms
Memory Limit: 65536 KiB
Problem Description
现在郭小冉决定在瓜场种m年西瓜。
首先他有n块西瓜地。
第i块西瓜地每年可以将会生产出b(i)颗西瓜。
每一年ta都会回到西瓜地。
每一年ta有两种操作,一种是选择一段连续的土地查询它们这些年的产量总和。
另外一种是选择一段连续的土地,并把它们的每一块的年产量都增加1.
Input
每组输入包含多组测试数据
对于每组测试数据
第一行包含西瓜地的块数n。
第二行包含n块西瓜地的年产量。
第三行包含m 代表接下来的年数。
每一年都会有一个操作
查询格式如下:
查询产量 Q s t (1<=s,t<=n)
增加年产量 I s t (1<=s,t<=n)
只有在查询的时候进行输出。
1<=n<=100000
1<=m<=100000
1<=b(i)<=100000
Output
对于每组测试,输出一行由空格隔开的整数(个数为输入中查询Q的个数)
Sample Input
4 1 1 1 1 3 Q 1 3 Q 1 4 Q 2 4 4 1 2 3 4 3 Q 1 4 I 1 3 Q 2 4
Sample Output
3 8 9 10 29
西安赛的时候根本没开这道题。。。
算是一道思维题。 你要查询的这个结果 就是 (b[i] + 增量)*当前年份 - 所有增量的对应的年份和。
显然,如果我们要知道每个增量是在第几年出现的,太麻烦了。
所以用了两个线段树,一个维护 (b[i] + 增量) 一个维护年份和。
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define ll long long #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define ms(x) memset(x, 0,sizeof(x)) const int MAXN = 100005; const int INF = 0x3f3f3f3f; ll add1[MAXN], add2[MAXN]; ll sum1[MAXN], sum2[MAXN]; inline void Scan(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } inline void Scanll(ll &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } void PushUp1(int rt) { sum1[rt] = sum1[rt<<1] + sum1[rt<<1|1]; } void PushUp2(int rt) { sum2[rt] = sum2[rt<<1] + sum2[rt<<1|1]; } void PushDown1(int rt, int m) { if(add1[rt]) { add1[rt<<1] += add1[rt]; add1[rt<<1|1] += add1[rt]; sum1[rt<<1] += add1[rt]*(m - (m>>1)); sum1[rt<<1|1] += add1[rt]*(m>>1); add1[rt] = 0; } } void PushDown2(int rt, int m) { if(add2[rt]) { add2[rt<<1] += add2[rt]; add2[rt<<1|1] += add2[rt]; sum2[rt<<1] += add2[rt]*(m - (m>>1)); sum2[rt<<1|1] += add2[rt]*(m>>1); add2[rt] = 0; } } void build1(int l, int r, int rt) { add1[rt] = 0; if(l == r) { // scanf("%lld",&sum1[rt]); Scanll(sum1[rt]); return ; } int m = (l+r)>>1; build1(lson); build1(rson); PushUp1(rt); } void build2(int l, int r, int rt) { add2[rt] = 0; if(l == r) { sum2[rt] = 0; return ; } int m = (l+r)>>1; build2(lson); build2(rson); PushUp2(rt); } void update1(int L, int R, int c, int l, int r, int rt) { if(L<=l && r<=R) { add1[rt] +=c; sum1[rt] += (ll)c*(r-l+1); return ; } PushDown1(rt, r-l+1); int m = (l+r)>>1; if(L<=m) update1(L,R,c,lson); if(m<R) update1(L,R,c,rson); PushUp1(rt); } void update2(int L, int R, int c, int l, int r, int rt) { if(L<=l && r<=R) { add2[rt] +=c; sum2[rt] += (ll)c*(r-l+1); return ; } PushDown2(rt, r-l+1); int m = (l+r)>>1; if(L<=m) update2(L,R,c,lson); if(m<R) update2(L,R,c,rson); PushUp2(rt); } ll query1(int L, int R, int l, int r, int rt) { if(L<=l && r<=R) { return sum1[rt]; } PushDown1(rt, r-l+1); int m = (l+r)>>1; ll ret = 0; if(L<=m) ret+=query1(L,R, lson); if(m<R) ret+=query1(L,R,rson); return ret; } ll query2(int L, int R, int l, int r, int rt) { if(L<=l && r<=R) { return sum2[rt]; } PushDown2(rt, r-l+1); int m = (l+r)>>1; ll ret = 0; if(L<=m) ret+=query2(L,R, lson); if(m<R) ret+=query2(L,R,rson); return ret; } vector<ll>vec; int main() { int n, m; while(scanf("%d", &n)!=EOF) { build1(1, n, 1); build2(1, n, 1); Scan(m); vec.clear(); for(int o=1; o<=m; o++) { int a, b; char ask[2]; scanf("%s",ask); Scan(a); Scan(b); if(ask[0] == 'Q') { ll ans = query1(a,b,1,n,1)*o - query2(a,b,1,n,1); // printf("1: %lld\n", query1(a,b,1,n,1)); // printf("2: %lld\n", query2(a,b,1,n,1)); vec.push_back(ans); } else if(ask[0] == 'I') { update1(a,b,1,1,n,1); update2(a,b,o,1,n,1); } } for(int i=0;i<vec.size();i++){ if(i) printf(" "); printf("%lld",vec[i]); } printf("\n"); } return 0; }