卿学姐与基本法 (线段树+离散化)

Posted happy_code

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了卿学姐与基本法 (线段树+离散化)相关的知识,希望对你有一定的参考价值。

“做专题也要按照基本法”

离开了诡异的村庄,卿学姐来到了威廉·圣·乱七八糟王国,这里的国王咸鱼王是个智障。

国家涣散,盗贼四起,民不聊生。

见到这样的景象,卿学姐不禁潸然泪下,“悠悠苍天,奈何苦了苍生”。

自幼学习基本法的卿学姐决定向整个国家普及基本法,改善国家法度。

在这个国家总共有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


以上是关于卿学姐与基本法 (线段树+离散化)的主要内容,如果未能解决你的问题,请参考以下文章

A - 卿学姐与公主(线段树+单点更新+区间极值)

卿学姐与魔法

卿学姐与公主

卿学姐与诡异村庄(并查集)

UESTC - 1324 卿学姐与公主

cdoj 1328 卿学姐与诡异村庄 Label:并查集 || 二分图染色