首页 > 代码库 > 玲珑oj 1117 线段树+离线+离散化,laz大法

玲珑oj 1117 线段树+离线+离散化,laz大法

1117 - RE:从零开始的异世界生活

Time Limit:1s Memory Limit:256MByte

Submissions:438Solved:68

DESCRIPTION

486到了异世界,看到了一群可爱的妹子比如蕾姆啊,艾米莉亚啊,拉姆啊,白鲸啊,怠惰啊等等!
有一天膜女告诉486说她的能力可能不能再用了,因为膜女在思考一个数据结构题,没心情管486了。
486说我来帮你做,膜女说你很棒棒哦!

给一个集合,最开始为空(不是数学上的集合)
五个操作:

1、插入x
2、把小于x的数变成x
3、把大于x的数变成x
4、求集合中第x小数
5、求集合中小于x的数个数

INPUT
第一行一个数m 后面有m行,每行格式为opt x,opt表示是什么操作,x表示操作的值
OUTPUT
对于每个4,5操作,输出一个值表示答案
SAMPLE INPUT
5 1 1 1 3 4 1 2 33 4 1
SAMPLE OUTPUT
1 33
HINT
m <= 100000 , x <= 1000000000
SOLUTION
“玲珑杯”ACM比赛 Round #14
这个题目是暑假前玲珑的一次我参加的比赛,很遗憾当时还很弱不会ST直接放弃了,现在又回来看见,当时看别人博客题解是什么值域线段树,好吧我也不会,
copy一个代码跑了960+ms险过感觉怎么这么慢捏,再次看题目感觉就是普通线段树就可做。
虽然n<1e9,但m最大10w,最多也就10w个不同的x,我想到用map离散化处理一下,为了方便询问我是从2开始的,由于要对所有的x离散化,所以必须先离散化结束才能应对所有的询问,这里采用了离线的作法,先保存询问值,预处理完在依次模拟询问的过程。
没有很奇葩的询问,单点更新,区间修改和二分查找,注意细节的话就好了。
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define inf 0x3f3f3f3f
  4 #define LL long long
  5 #define MAX 100005
  6 map<int,int>M1;
  7 int N,x[MAX]={2147483647},P[MAX];
  8 struct Ask
  9 {
 10   int opt,x;
 11 }a[MAX];
 12 struct SegTree
 13 {
 14   #define M ((L+R)>>1)
 15   #define lc (id<<1)
 16   #define rc (id<<1|1)
 17   int sum[MAX<<2],laz[MAX<<2];//laz[i]表示全部变为i
 18   void init()
 19   {
 20       memset(sum,0,sizeof(sum));
 21       memset(laz,-1,sizeof(laz));
 22   }
 23   void pushup(int L,int R,int id)
 24   {
 25       sum[id]=sum[lc]+sum[rc];
 26   }
 27   void pushdown(int L,int R,int id)
 28   {
 29       if(laz[id]!=-1){
 30         sum[lc]=sum[rc]=0;
 31         laz[lc]=laz[rc]=0;
 32         laz[id]=-1;
 33       }
 34   }
 35   void irt(int L,int R,int id,int x,int v)
 36   {
 37       if(L==R){
 38         sum[id]+=v;
 39         return;
 40       }
 41       pushdown(L,R,id);
 42       if(x<=M) irt(L,M,lc,x,v);
 43       else     irt(M+1,R,rc,x,v);
 44       pushup(L,R,id);
 45   }
 46   int change(int L,int R,int id,int l,int r)
 47   {
 48      if(L>=l&&R<=r){
 49         int res=sum[id];
 50         sum[id]=0;
 51         laz[id]=0;
 52         return res;
 53      }
 54      pushdown(L,R,id);
 55      int res=0;
 56      if(l<=M) res+=change(L,M,lc,l,r);
 57      if(r>M)  res+=change(M+1,R,rc,l,r);
 58      pushup(L,R,id);
 59      return res;
 60   }
 61   int ask1(int L,int R,int id,int x)
 62   {
 63       if(L==R) return P[L];
 64       pushdown(L,R,id);
 65       if(sum[lc]>=x){
 66         return ask1(L,M,lc,x);
 67       }
 68       else{
 69         return ask1(M+1,R,rc,x-sum[lc]);
 70       }
 71   }
 72   int ask2(int L,int R,int id,int x)
 73   {
 74       if(L==R) return sum[id];
 75       pushdown(L,R,id);
 76       if(x<=M) return ask2(L,M,lc,x);
 77       else if (x>M) return sum[lc]+ask2(M+1,R,rc,x);
 78   }
 79 
 80 }seg;
 81 int main()
 82 {
 83     //freopen("in.txt","r",stdin);
 84     int n,m,i,j,k;
 85     scanf("%d",&n); N=1;
 86     for(i=1;i<=n;++i)
 87     {
 88         scanf("%d%d",&a[i].opt,&a[i].x);
 89         x[i]=a[i].x;
 90     }
 91     sort(x+1,x+n+1);
 92     for(i=1;i<=n;++i)
 93     {
 94        if(x[i]==x[i-1]) continue;
 95        M1[x[i]]=++N;
 96        P[N]=x[i];
 97     }
 98     N++;
 99     seg.init();
100     for(i=1;i<=n;++i)
101     {
102         int x1=M1[a[i].x];
103         if(a[i].opt==1){
104             seg.irt(1,N,1,x1,1);
105         }
106         else if(a[i].opt==2){
107             seg.irt(1,N,1,x1,seg.change(1,N,1,1,x1-1));
108         }
109         else if(a[i].opt==3){
110             seg.irt(1,N,1,x1,seg.change(1,N,1,x1+1,N));
111         }
112         else if(a[i].opt==4){
113             printf("%d\n",seg.ask1(1,N,1,a[i].x));
114         }
115         else if(a[i].opt==5){
116             printf("%d\n",seg.ask2(1,N,1,x1-1));
117         }
118     }
119     return 0;
120 }

 

玲珑oj 1117 线段树+离线+离散化,laz大法