Range of Data


Operation 1和Operation 2是没有本质上的区别的,二者相当于给区间[i,j]进行加减值val。通过分析,知道最大值和最小值只会出现在区间的端点,或者是i的左边和j的右边,由于M次操作,加上初始时的最小点(1)和最大点(N),因此只需最多考虑4*M+2。
对区间[i,j]的操作,采取如下处理方式,在位置i加上val,位置j+1加上-val,因为j+1是未被操作的,这样当累计val到j+1时,对j+1来说该操作的实际值为0。每一次的操作添加4个点(i-1,0),(i,val),(j,0),(j+1,-val)。之后对这些点进行排序,依次遍历这些点,并将他们更新后的值与当前的minval,maxval进行比较。

const int maxs = 40010;
int n,m;
int a,x,y,b; 
pair<int,int> papers[maxs];
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        int cnt = 0;
        papers[cnt++] = MP(1,0);
        papers[cnt++] = MP(n,0);
        while(m--)
        {
            scanf("%d %d %d %d",&a,&x,&y,&b);
            if (a==2) b =-b;
            if (x>1) papers[cnt++] = MP(x-1,0);
            papers[cnt++] = MP(x,b);
            papers[cnt++] = MP(y,0);
            if (y<n) papers[cnt++] = MP(y+1,-b);
        }
        sort(papers,papers+cnt);
        //for(int i=0;i<cnt;i++) cout << papers[i].first << " " << papers[i].second << endl;
        int minv = 2000000000;
        int maxv =-2000000000;
        int add = 0,cur=1;
        for(int i=0;i<=cnt;i++)
        {
            if (i<cnt && cur == papers[i].first) {add += papers[i].second;continue;}
            else
            {
                if(cur+add<minv) minv = cur + add;
                if(cur+add>maxv) maxv = cur + add;
                if (i<cnt){
                    add += papers[i].second;
                    cur = papers[i].first;
                }
            }
        }
        printf("%d\n",maxv-minv);
    }
    return 0;
}

参考:
http://www.codechef.com/AUG12/problems/DRANGE
http://discuss.codechef.com/problems/DRANGE

posted @ 2012-08-17 21:33  4T-Shirt  阅读(225)  评论(0)    收藏  举报