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

浙公网安备 33010602011771号