1. 程式人生 > >卿學姐與基本法 (線段樹+離散化)

卿學姐與基本法 (線段樹+離散化)

esp rdquo fine truct r+ lose row log ram

“做專題也要按照基本法”

離開了詭異的村莊,卿學姐來到了威廉·聖·亂七八糟王國,這裏的國王鹹魚王是個智障。

國家渙散,盜賊四起,民不聊生。

見到這樣的景象,卿學姐不禁潸然淚下,“悠悠蒼天,奈何苦了蒼生”。

自幼學習基本法的卿學姐決定向整個國家普及基本法,改善國家法度。

在這個國家總共有NN個人,每個人都有一個編號,編號從1開始。

由於整個國家的人實在是太多了,卿學姐每次只能對一個連續區間的編號的人普及基本法。

同時卿學姐還想知道在某個時刻某個區間還有多少人沒有被普及基本法。

Input

第一行兩個整數

N,Q表示總共有N個人,並且有Q次事件。

接下來QQ行,每行三個整數t,L,R。如果t1,代表在這時,卿學姐向閉區間L,R的人普及基本法。如果t是2,代表在這時,卿學姐想知道閉區間L,R裏面有多少人還沒有被普及基本法。

1≤N≤100000000

1≤Q≤100000

1≤t≤2

1≤L≤R≤N

Output

輸出每個卿學姐想知道的答案

Sample Input

5 3
1 1 2
1 4 5
2 2 4

Sample Output

1


//顯然,若是對於每個人都當節點來考慮的話,是會爆內存的,
因為操作數比較小,在可接受的範圍內,所以,將所有可能用到的 l,r 抽離出來,例如如果只操作 1 5 9 12 ,就將 1 5 9 12 抽出來建樹,1代表 [1,5),9代表[9,12) 這樣就是離散化了
但是,有個小問題,比如我要查詢 1-5 ,只能查詢到 [1,9),顯然不對, 所以,需要把右邊,+1 後離散建樹
例如,如果上面的輸入時是
1 1 5
1 9 12
2 5 9
建樹的點即為 1 5 6 9 12 13 5 9 10
然後排序去重,即可 1 5 6 9 10 12 13
技術分享
  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <set>
  5 #include <map>
  6 #include <algorithm>
  7
using namespace std; 8 #define MX 100005 9 10 struct Node 11 { 12 int l,r; 13 int lazy; 14 int sum; //已經普法人數 15 int len; //實際人數 16 }node[MX*12]; 17 18 struct Op 19 { 20 int op; 21 int l,r; 22 }opr[MX]; 23 24 int n,q; 25 int point[MX*4]; 26 map<int,int> dex; 27 28 void Init(int l,int r,int k) 29 { 30 node[k]=(Node){l,r,0,point[r]-point[l]+1}; 31 if (l==r) return ; 32 int mid = (l+r)/2; 33 Init(l,mid,2*k); 34 Init(mid+1,r,2*k+1); 35 } 36 37 void push_down(int k) 38 { 39 node[k*2].lazy=1; 40 node[k*2].sum=node[k*2].len; 41 node[k*2+1].lazy=1; 42 node[k*2+1].sum=node[k*2+1].len; 43 node[k].lazy=0; 44 } 45 46 void update(int l,int r,int k) 47 { 48 if (l==node[k].l&&r==node[k].r) 49 { 50 node[k].lazy=1; 51 node[k].sum=node[k].len; 52 return; 53 } 54 if (node[k].lazy) push_down(k); 55 int mid = (node[k].l+node[k].r)/2; 56 if (l>mid) update(l,r,2*k+1); 57 else if (r<=mid) update(l,r,2*k); 58 else 59 { 60 update(l,mid,2*k); 61 update(mid+1,r,2*k+1); 62 } 63 node[k].sum = node[2*k].sum+node[2*k+1].sum; 64 } 65 66 int inquery(int l,int r,int k) 67 { 68 if (l==node[k].l&&r==node[k].r) 69 { 70 return node[k].sum; 71 } 72 if (node[k].lazy) push_down(k); 73 int mid = (node[k].l+node[k].r)/2; 74 if (l>mid) return inquery(l,r,2*k+1); 75 else if (r<=mid) return inquery(l,r,2*k); 76 return inquery(l,mid,2*k)+inquery(mid+1,r,2*k+1); 77 } 78 79 int main() 80 { 81 scanf("%d%d",&n,&q); 82 int pn=1; 83 for (int i=0;i<q;i++) 84 { 85 scanf("%d%d%d",&opr[i].op,&opr[i].l,&opr[i].r); 86 point[pn++]=opr[i].l; 87 point[pn++]=opr[i].r; 88 point[pn++]=opr[i].r+1; // 很關鍵 89 } 90 pn--; 91 sort(point+1,point+1+pn); 92 pn = unique(point+1,point+1+pn)-(point+1); 93 94 for (int i=1;i<=pn;i++) 95 dex[point[i]]=i; 96 Init(1,pn,1); 97 98 for(int i=0;i<q;i++) 99 { 100 int l=dex[opr[i].l]; 101 int r=dex[opr[i].r]; 102 if (opr[i].op==1) 103 update(l,r,1); 104 else 105 printf("%d\n",inquery(l,r,1)); 106 } 107 return 0; 108 }
View Code


卿學姐與基本法 (線段樹+離散化)