种西瓜
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;
}