- Step1 Problem
原题
一个人有很多家公司给他了offer,但是他看了看觉得薪水都太低了,并不想参加,于是决定回家种地。(任性啊,这个人)
他在家里开始种西瓜,家里一共有n块瓜田,每年可以产出ai个西瓜。每年亮皇回家的时候都会看看他种的这块地,他会做以下下两种操作之一:
1、询问一段土地从第一年开始,到当年结束一共生产了多少个西瓜。
2、在一段土地上种上黄豆,这样可以让这块西瓜地从下一年开始产量+1。(种豆得瓜?)
某人一共会回家m年,请你帮他回答所有的查询。
- Step2 Ideas:
这题需要你求出从第一年开始一共生产的瓜,那就恶心了,一个线段树的裸题硬生生成了个送命题(只是对我来说),那问题在于怎么去维护线段树的区间信息,一开始想维护总产量,写到后面又出现了不好加去年产量的问题,又想用map去存他是第几年更新的这个点,尴尬在于不会用map<int, pair<int, int> > ,STL还是太菜,又然后、、、、就想到了用两棵树去做了,一棵树就单纯的维护单产,又一棵树去维护这个区间在第几年加了buff,然后最终的答案就可以写为 总产 = 单产*年数 - 修改他的年份。(顺便吐槽一下自己,想到一个方法因为没有写过两个线段树的题就不敢写?如果敢于动键盘顺着思路下去没什么难的,还有就是这STL真的太菜了,虽然我用map的想法不一定对,但死在不会用上就很难受了。。)
- Step3 Code:
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#define lt k<<1
#define rt k<<1|1
using namespace std;
typedef long long ll;
const ll N = 1e5+5;
const int inf = 0x3f3f3f3f;
struct node
{
ll ltree, rtree;
ll sum, lazy;
} tree[N<<2], tree1[N<<2];
ll n, q, ans[N];
void pushdown(node *tree, ll k)
{
tree[lt].sum += tree[k].lazy * (tree[lt].rtree - tree[lt].ltree + 1);
tree[rt].sum += tree[k].lazy * (tree[rt].rtree - tree[rt].ltree + 1);
tree[lt].lazy += tree[k].lazy, tree[rt].lazy += tree[k].lazy;
tree[k].lazy = 0;
}
void build(node *tree, ll l, ll r, ll k, ll pos)
{
tree[k].ltree = l, tree[k].rtree = r;
tree[k].lazy = 0;
if(l == r)
{
if(pos) cin >> tree[k].sum;
else tree[k].sum = 0;
return ;
}
ll mid = (l + r)>>1;
build(tree, l, mid, lt, pos);
build(tree, mid+1, r, rt, pos);
tree[k].sum = tree[lt].sum + tree[rt].sum;
}
ll query(node *tree, ll l, ll r, ll k)
{
ll L = tree[k].ltree, R = tree[k].rtree;
if(l <= L && r >= R) return tree[k].sum;
if(tree[k].lazy) pushdown(tree, k);
ll mid = (L + R)>>1;
if(r <= mid) return query(tree, l, r, lt);
else if(l > mid) return query(tree, l, r, rt);
else return query(tree, l, mid, lt) + query(tree, mid+1, r, rt);
}
void uptade(node *tree, ll l, ll r, ll k, ll num)
{
ll L = tree[k].ltree, R = tree[k].rtree;
if(L == l && R == r)
{
tree[k].sum += (R - L + 1)*num;
tree[k].lazy += num;
return ;
}
if(tree[k].lazy) pushdown(tree, k);
ll mid = (L + R)>>1;
if(mid >= r) uptade(tree, l, r, lt, num);
else if(mid < l) uptade(tree, l, r, rt, num);
else
{
uptade(tree, l, mid, lt, num);
uptade(tree, mid+1, r, rt, num);
}
tree[k].sum = tree[lt].sum + tree[rt].sum;
}
int main()
{
ios::sync_with_stdio(false);
while(cin >> n)
{
build(tree, 1, n, 1, 1);
build(tree1, 1, n, 1, 0);
char c;
cin >> q;
ll tot = 0;
for(ll i = 1; i <= q; i++)
{
cin >> c;
if(c == 'Q')
{
ll a, b;
cin >> a >> b;
ll sum = query(tree, a, b, 1);
ll sum1 = query(tree1, a, b, 1);
ans[tot++] = sum*i - sum1;
}
else
{
ll a, b;
cin >> a >> b;
uptade(tree, a, b, 1, 1);
uptade(tree1, a, b, 1, i);
}
}
for(ll i = 0; i < tot; i++)
{
if(!i) cout << ans[i];
else cout << ' ' << ans[i];
}
cout << endl;
}
return 0;
}