zoj 2706 线段树

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1706

trick:关于正数和负数的整除问题,正数整除是自动向下取整的,但负数是向上取整的
即13/3=4.3 ->4 但-13/3=-4.3 ->-4

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>

#define maxn 32500
#define maxe 11000
#define INF  0x3f3f3f
#define lson l,mid,u<<1
#define rson mid+1,r,u<<1|1
#define ll_int long long int
using namespace std;

ll_int seg[maxn<<2];
ll_int pau[maxn<<2];
//bool   flag[maxn<<2];
ll_int initsum;
void PushUp(int u){
    seg[u] = seg[u<<1] + seg[u<<1|1];
}
void PushDown(int l,int r,int u){
    if(pau[u]){
        int mid = (l + r)/2;
        pau[u<<1] = pau[u<<1|1] = pau[u];
        seg[u<<1] = (ll_int)(mid - l + 1) * pau[u];
        seg[u<<1|1] = (ll_int)(r - mid) * pau[u];
        pau[u] = 0;
    }
}
void build(int l,int r,int u){
    seg[u] = 0;
    pau[u] = 0;
    if(l == r){
        scanf("%lld",&seg[u]); 
        initsum += seg[u];
        return;
    }
    int mid = (l + r)/2;
    build(lson);
    build(rson);
    PushUp(u);
}

void Update(int L,int R,int num,int l,int r,int u){
    if(L <= l && r <= R){
        pau[u] = num;
        seg[u] = (ll_int)(r - l + 1)* num;
        return;
    }
    PushDown(l,r,u);
    int mid = (l + r)/2;
    if(L <= mid)       Update(L,R,num,lson);
    if(R >  mid)       Update(L,R,num,rson);
    PushUp(u);  //要记住啊 
}

ll_int Query(int L,int R,int l,int r,int u){
    if(L <= l && r <= R){
        return seg[u];
    }
    PushDown(l,r,u); 
    int mid = (l + r)/2;
    ll_int ret = 0;
    if(L <= mid)  ret += Query(L,R,lson);
    if(R >  mid)  ret += Query(L,R,rson);
    return ret;
}
void print(int l,int r,int u){
    if(l == r){
        if(l == 1) printf("%lld",seg[u]);
        else       printf(" %lld",seg[u]);
        return;
    } 
    PushDown(l,r,u);
    int mid = (l + r)/2;
    print(lson);
    print(rson);
}
int main(){
//    freopen("input.txt","r",stdin);
    int n,m;
    while(scanf("%d%d",&n,&m) == 2){
        initsum = 0;
        build(1,n,1);
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            
            ll_int sum = Query(a,b,1,n,1);
            int ave = sum/(b-a+1);
            
            if(sum > 0 && seg[1] <= initsum){  //为正的UP;
                if(sum % (b-a+1)) ave++;
            }
            else if(sum < 0 && seg[1] > initsum){ //为负的down; 
                if(sum % (b-a+1)) ave--;
            }
            
            Update(a,b,ave,1,n,1);
        }
        print(1,n,1);
        printf("\n\n");
    } 
}
View Code

 

posted @ 2013-08-05 01:50  等待最好的两个人  阅读(226)  评论(0编辑  收藏  举报