2018icpc徐州网络赛-H Ryuji doesn't want to study(线段树)

题意:

有n个数的一个数组a,有两个操作:

1 l r:查询区间[l,r]内$a[l]*(r-l+1)+a[l+1]*(r-l)+a[l+2]*(r-l-1)+\cdots+a[r-1]*2+a[r]$

2 l r:将a[l]修改为r

n<=1e5,  a[i]<=1e9

思路:

预处理出前缀和s[i], 则操作1变为查询$s[l]+s[l+1]+..+s[r]-(r-l+1)*s[l-1]$

为防止爆ll(其实也不会爆的)可以在查询操作力就提前减去s[l-1]

坑点来了。。操作2即区间s(l,n)加上r-a[l],由于我们线段树里的一些标记操作,实际上a[i]和s[i]数组并没有变!

所以我们每次需要用s或a数组的时候都要query。。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 1e6+5000;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);
ll sum[maxn<<2];
ll s[maxn];
ll a[maxn];
int ii;
void build(int l, int r, int root){
    int mid = l + ((r - l) >> 1);//位运算TMD优先级! 
    if(l == r){
        sum[root] = s[l];
        return;
    }
    build(lson);
    build(rson);
    sum[root] = sum[lc]+sum[rc];
}

ll addv[maxn << 2];
//将root的信息传到左右节点上
void pushup(int root){
    sum[root] = sum[lc] + sum[rc];
    return;
}
void pushdown(int l, int r, int root){
    if(addv[root]){
        addv[lc] += addv[root];
        addv[rc] += addv[root];
        int mid = l + ((r-l)>>1);
        sum[lc] += addv[root]*(mid-l+1);
        sum[rc] += addv[root]*(r-mid);
        addv[root] = 0;
    }
    return;
}
void update(int ql, int qr, ll add, int l, int r, int root){
    if(ql <= l && qr >= r){
        addv[root] += add;
        sum[root] += add*(r-l+1);
        return;
    }
    pushdown(l, r, root);
    int mid = l + ((r-l)>>1);
    if(ql <= mid) update(ql, qr, add, lson);
    if(qr > mid) update(ql, qr, add, rson);
    pushup(root);
    return;
}
ll query(int ql, int qr, int l, int r, int root){
    if(ql==0)return 0;
    if(ql <= l && qr >= r) return sum[root];//(sum[root]-(ll)((ll)r-l+1)*s[ii-1]);
    pushdown(l, r, root);
    int mid = l + ((r-l)>>1);
    ll ans = 0;
    if(ql <= mid) ans += query(ql, qr, lson);
    if(qr > mid)  ans += query(ql, qr, rson);
    return ans;
}
int main() {
    int n, q;
    scanf("%d %d", &n, &q);
    for(int i =1; i <= n ; i++){
        scanf("%lld", &a[i]);
    }s[0] = 0;
    mem(s, 0);
    for(int i = 1; i <= n; i++){
        s[i] = a[i]+s[i-1];
    }
    mem(addv, 0);
    mem(sum, 0);
    build(1, n, 1);
    while(q--){
        int c,l,r;
        scanf("%d %d %d", &c, &l, &r);
        if(c==1){
            ii = l;
            printf("%lld\n", query(l, r, 1, n, 1) -(r-l+1)*query(l-1,l-1,1,n,1));
        }  
        else if(c==2){
            ll tmp = (ll)r-(query(l, l, 1, n, 1) -query(l-1, l-1, 1, n, 1));
            update(l, n, tmp, 1, n, 1);
        }A
    }
    return 0;
}
/*
5 10
1000000000 1000000000 1000000000 1000000000 1000000000
1 2 4
2 1 0
1 2 4
 */

 

posted @ 2018-09-10 16:14  wrjlinkkkkkk  阅读(204)  评论(0编辑  收藏  举报