【线段树】结训赛— H - 【金色】种瓜得瓜,种豆得豆

 

  • 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;
}
posted @ 2019-02-23 02:50  Mr.XuAMis.Liu  阅读(159)  评论(0编辑  收藏  举报