Test instructions: There are n small blocks of wood composed of a long block to fall down, give the right and left of the block, and then to the M-plank of the left and right intervals and height to catch the block, because the wood is made of small wood contact, that is, the plank can catch part of the wood, the remaining will continue to fall, Ask how many small pieces of wood are on each board at the end.
Solution: This problem with a line tree can be solved, there is another more witty approach.
First say the segment tree, the left and right interval to 3x1e7, if the line tree to solve the need for discretization. After sorting the planks from low to high, use a segment tree flag to maintain the corresponding plank number for each interval, so that the tall planks can cover the low plank number, and then use another line tree sum to maintain the number of each block in each interval, since it is possible for n blocks to overlap. So there is not only a row of small blocks in a range, then each update of a long block of wood, corresponding to the interval of the number of blocks plus 1. The last query of each interval of the total number of small wooden blocks is the corresponding length of the block number of blocks multiplied by the interval, the first has been the MLE, and then the discrete map for two points to find the water passed.
Here's the code for the line tree approach:
#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace STD;Const intN =100001;structBoard {intL, R, h, id;} Boa[n];intN, M, L[n], r[n];Long LongRes[n];intSum[n <<4], Flag[n <<4]; vector<int>ABOOLcmpConstboard& A,Constboard& b) {returnA.h < B.h;}voidPushdown (intK) {if(Flag[k]) {Flag[k *2] = Flag[k *2+1] = Flag[k]; FLAG[K] =0; }if(Sum[k]) {Sum[k *2] + = Sum[k]; Sum[k *2+1] + = Sum[k]; SUM[K] =0; }}voidModify1 (intKintLeftintRightintL1,intR1,intx) {if(L1 <= left && right <= R1) {Flag[k] = x;return; } pushdown (k);intMid = (left + right)/2;if(L1 < mid) modify1 (k *2, left, Mid, L1, R1, X);if(R1 > Mid) modify1 (k *2+1, Mid, right, L1, R1, x);}voidModify2 (intKintLeftintRightintL1,intR1) {if(L1 <= left && right <= R1) {sum[k]++;return; } pushdown (k);intMid = (left + right)/2;if(L1 < mid) modify2 (k *2, left, Mid, L1, R1);if(R1 > Mid) modify2 (k *2+1, Mid, right, L1, R1);}voidQueryintKintLeftintright) {if(Flag[k]) {Res[flag[k]] + = (Long Long) sum[k] * (A[right]-a[left]);return; }if(Left +1= = right)return; Pushdown (k);intMid = (left + right)/2; Query (k *2, left, mid); Query (k *2+1, Mid, right);}intMain () { while(scanf("%d%d", &n, &m) = =2) {a.clear ();memset(Sum,0,sizeof(sum));memset(Flag,0,sizeof(flag));memset(Res,0,sizeof(res)); for(inti =1; I <= N; i++) {scanf("%d%d", &l[i], &r[i]); A.push_back (L[i]); A.push_back (R[i]); } for(inti =1; I <= m; i++) {scanf("%d%d%d", &BOA[I].L, &BOA[I].R, &boa[i].h); Boa[i].id = i; A.push_back (BOA[I].L); A.push_back (BOA[I].R); } sort (A.begin (), A.end ()); A.erase (Unique (A.begin (), A.end ()), A.end ());intCNT = A.size (); Sort (boa +1, Boa +1+ M, CMP); for(inti =1; I <= m; i++) {intPOS1 = Lower_bound (A.begin (), A.end (), BOA[I].L)-A.begin ();intPos2 = Lower_bound (A.begin (), A.end (), BOA[I].R)-A.begin (); Modify1 (1,0, CNT-1, POS1, Pos2, boa[i].id); } for(inti =1; I <= N; i++) {intPOS1 = Lower_bound (A.begin (), A.end (), l[i])-A.begin ();intPos2 = Lower_bound (A.begin (), A.end (), r[i])-A.begin (); Modify2 (1,0, CNT-1, POS1, Pos2); } query (1,0, CNT-1); for(inti =1; I <= m; i++)printf("%lld\n", Res[i]);printf("\ n"); }return 0;}
Another approach is to look at other people's solution, fast and Fast code is short (like to write code short ╮(╯▽╰)╭), do not need to be discretized, all the wood blocks and boards of the area from left to right scanning side, combined with drawing very well understood.
#include <cstdio>#include <cstring>#include <map>#include <algorithm>using namespace STD;Const intN =100005;structBoard {intH, L, R;Long LongNum;} Boa[n <<2];structNode {intSt, id, v;//Interval starting point, distinguish between wood block or plank, distinguish left and right end}node[n <<2];intN, M; map<int,int>mp//Save all planks in the current processing range, the left value is the plank height, the right value is the plank corresponding numberBOOLcmpConstnode& A,Constnode& b) {if(A.St! = b.st)returnA.St < B.st;returnA.V < B.V;}intMain () { while(scanf("%d%d", &n, &m) = =2) {mp.clear ();intCNT =0, L, R; for(inti =1; I <= N; i++) {scanf("%d%d", &l, &r); Node[++cnt].st = L, node[cnt].id =0, NODE[CNT].V =1; Node[++cnt].st = r, Node[cnt].id =0, NODE[CNT].V =-1; } for(inti =1; I <= m; i++) {scanf("%d%d%d", &BOA[I].L, &BOA[I].R, &boa[i].h); Boa[i].num =0; Node[++cnt].st = boa[i].l, node[cnt].id = i, node[cnt].v =1; Node[++cnt].st = BOA[I].R, node[cnt].id = i, node[cnt].v =-1; } Sort (node +1, node +1+ CNT, CMP);intPre = node[0].st, cnt1 =0;//Current processing interval starting point, number of bars in the current interval for(inti =1; I <= CNT; i++) {if(Mp.rbegin ()! = Mp.rend ()) {//map automatic sorting, so the last value in the map must be the largest, the tallest plank intid = mp.rbegin ()-second;//Right value is numberBoa[id].num + = (Long Long) (node[i].st-pre) * CNT1;//small wooden block number is the length of the block}if(!node[i].id) {//Current processing interval is a block of wood if(NODE[I].V = =1) cnt1++;//bar number plus 1 Elsecnt1--; }Else{//Plank if(NODE[I].V = =1)///Left point join BoardMp[boa[node[i].id].h] = node[i].id;Else//Right end point remove plankMp.erase (boa[node[i].id].h); } pre = Node[i].st;//update processing interval starting point} for(inti =1; I <= m; i++)printf("%lld\n", Boa[i].num);printf("\ n"); }return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Zoj 3299 (interval modification + discretization)