sdut4259种西瓜 [原题: 2018西安邀请赛K题]【线段树】

种西瓜

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;
}


猜你喜欢

转载自blog.csdn.net/khn64/article/details/80747660
今日推荐