值域线段树 (玲珑OJ 1117)

点击打开题目链接

题目意思很简单:

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


思路: 线段树,节点是值的分数,你可以离散,也可以不离散,直接标记;我的写法是:   看代码注释>>>


据说数组改为指针会快点;代码比较挫.存一个;

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <vector>
  5 #include <iostream>
  6 using namespace std;
  7 
  8 typedef long long int LL;
  9 const LL INF=1000000000;
 10 const int maxn=6e6+100;
 11 
 12 
 13 struct ACM
 14 {
 15     struct segment
 16     {
 17         int val,lson,rson;
 18         bool mark;
 19     } seg[maxn];
 20     int sz;
 21     /***
 22         开辟新的节点并初始化
 23     */
 24     int newnode()
 25     {
 26         sz++;
 27         if(sz>=maxn)
 28         {
 29             int lzq=5,zhangpan=0;
 30             lzq=lzq/zhangpan;
 31 
 32         }
 33         seg[sz].lson=seg[sz].rson=-1;
 34         seg[sz].val=0,seg[sz].mark=false;
 35         return sz;
 36     }
 37     /***
 38         初始化根节点
 39     */
 40     void init(int& root)
 41     {
 42         sz=-1;
 43         root=newnode();
 44     }
 45     /***
 46         标记下放操作,如果没有节点开辟新的节点;
 47     */
 48     void pushdown(int i) 
 49     {
 50         int l=seg[i].lson,r=seg[i].rson;
 51         if(l==-1) seg[i].lson=newnode();
 52         if(r==-1) seg[i].rson=newnode();
 53         if(seg[i].mark)
 54         {
 55             seg[i].mark=false;
 56             seg[l].mark=seg[r].mark=true;
 57             seg[l].val=seg[r].val=0;
 58         }
 59     }
 60     void pushup(int i)
 61     {
 62         int l=seg[i].lson,r=seg[i].rson;
 63         seg[i].val=seg[l].val+seg[r].val;
 64     }
 65     /***
 66         插入函数 ; 在 pos 位置上面加上 val;
 67     */
 68     void ins(int i,int l,int r,int pos,int val)
 69     {
 70         if(l==r)
 71         {
 72             seg[i].val+=val;
 73             return ;
 74         }
 75         pushdown(i);
 76         int mid=(l+r)>>1;
 77         if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
 78         else ins(seg[i].rson,mid+1,r,pos,val);
 79         pushup(i);
 80     }
 81     /***
 82         将 L,R 这段区间上的值,更新为 0;
 83     */
 84     void del(int i,int l,int r,int L,int R)
 85     {
 86         if(l==L&&r==R)
 87         {
 88             seg[i].val=0;
 89             seg[i].mark=true;
 90             return ;
 91         }
 92         pushdown(i);
 93         int mid=(l+r)>>1;
 94         if(R<=mid) del(seg[i].lson,l,mid,L,R);
 95         else if(L>mid) del(seg[i].rson,mid+1,r,L,R);
 96         else del(seg[i].lson,l,mid,L,mid),del(seg[i].rson,mid+1,r,mid+1,R);
 97         pushup(i);
 98     }
 99     int find(int i,int l,int r,int x) //第x小的数字;
100     {
101         if(l==r) return l;
102         pushdown(i);
103         int lval=0;
104         int mid=(l+r)>>1;
105         if(seg[i].lson!=-1) lval=seg[seg[i].lson].val;
106         if(x<=lval) return find(seg[i].lson,l,mid,x);
107         else return find(seg[i].rson,mid+1,r,x-lval);
108     }
109     int query(int i,int l,int r,int L,int R) //区间 数的个数;
110     {
111         if(l==L&&r==R) return seg[i].val;
112         pushdown(i);
113         int mid=(l+r)>>1;
114         if(R<=mid) return query(seg[i].lson,l,mid,L,R);
115         else if(L>mid) return query(seg[i].rson,mid+1,r,L,R);
116         else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+1,r,mid+1,R);
117     }
118 } AC;
119 
120 
121 
122 int main()
123 {
124     int m;
125     scanf("%d",&m);
126     int op,x,root,temp;
127     AC.init(root);
128     while(m--)
129     {
130         scanf("%d%d",&op,&x);
131         switch(op)
132         {
133         case 1:
134             AC.ins(root,0,INF,x,1);
135             break;
136         case 2:
137             temp=AC.query(root,0,INF,0,x);
138             AC.del(root,0,INF,0,x);
139             AC.ins(root,0,INF,x,temp);
140             break;
141         case 3:
142             temp=AC.query(root,0,INF,x,INF);
143             AC.del(root,0,INF,x,INF);
144             AC.ins(root,0,INF,x,temp);
145             break;
146         case 4:
147             printf("%d\n",AC.find(root,0,INF,x));
148             break;
149         case 5:
150             printf("%d\n",AC.query(root,0,INF,0,x-1));
151             break;
152         }
153     }
154     return 0;
155 }

 


 

代码二:

 

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <vector>
  5 #include <iostream>
  6 using namespace std;
  7 
  8 const int INF=1000000000;
  9 const int maxn=6e6+100;
 10 struct ACM
 11 {
 12     /***
 13         对于 2,3 操作,先查询个数,再插入这个数字:
 14         意思就是更新到底部,加上查询出来的个数;
 15         并加上清零的标记;
 16         
 17     */
 18     struct Node
 19     {
 20         int val,lson,rson;
 21         bool mark;
 22     } seg[maxn];
 23     int sz;
 24     int newnode()
 25     {
 26         sz++;
 27         seg[sz].val=0;
 28         seg[sz].lson=-1;
 29         seg[sz].rson=-1;
 30         seg[sz].mark=false;
 31         return sz;
 32     }
 33     void init(int& root)
 34     {
 35         sz=-1;
 36         root=newnode();
 37     }
 38     void pushdown(int i)
 39     {
 40         int l=seg[i].lson,r=seg[i].rson;
 41         if(l==-1) seg[i].lson=newnode();
 42         if(r==-1) seg[i].rson=newnode();
 43         if(seg[i].mark)
 44         {
 45             seg[i].mark=false;
 46             seg[l].mark=seg[r].mark=true;
 47             seg[l].val=seg[r].val=0;
 48         }
 49     }
 50     void pushup(int i)
 51     {
 52         int l=seg[i].lson,r=seg[i].rson;
 53         seg[i].val=seg[l].val+seg[r].val;
 54     }
 55     int query(int i,int l,int r,int L,int R) //区间 数的个数;
 56     {
 57         if(l==L&&r==R) return seg[i].val;
 58         pushdown(i);
 59         int mid=(l+r)>>1;
 60         if(R<=mid) return query(seg[i].lson,l,mid,L,R);
 61         else if(L>mid) return query(seg[i].rson,mid+1,r,L,R);
 62         else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+1,r,mid+1,R);
 63     }
 64     void ins(int i,int l,int r,int pos,int val)
 65     {
 66         if(l==r)
 67         {
 68             seg[i].val+=val;
 69             return ;
 70         }
 71         pushdown(i);
 72         int mid=(l+r)>>1;
 73         if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
 74         else ins(seg[i].rson,mid+1,r,pos,val);
 75         pushup(i);
 76     }
 77     void operator2(int i,int l,int r,int x,int val)
 78     {
 79         if(l==r)
 80         {
 81             seg[i].val=val;
 82             return ;
 83         }
 84         int mid=(l+r)>>1;
 85         pushdown(i);
 86         if(x<=mid) operator2(seg[i].lson ,l,mid,x,val);
 87         else
 88         {
 89             seg[seg[i].lson].mark=true;
 90             seg[seg[i].lson].val=0;//如果,存在加到某一边,不存在也需要开新的节点!!
 91             operator2(seg[i].rson,mid+1,r,x,val);
 92         }
 93         pushup(i);
 94     }
 95     void operator3(int i,int l,int r,int x,int val)
 96     {
 97         if(l==r)
 98         {
 99             seg[i].val=val;
100             return ;
101         }
102         pushdown(i);
103         int mid=(l+r)>>1;
104         if(x<=mid)
105         {
106             seg[seg[i].rson].mark=true;
107             seg[seg[i].rson].val=0;
108             operator3(seg[i].lson,l,mid,x,val);
109         }
110         else operator3(seg[i].rson,mid+1,r,x,val);
111         pushup(i);
112     }
113     int operator4(int i,int l,int r,int x)
114     {
115         if(l==r) return l;
116         int mid=(l+r)>>1;
117         pushdown(i);
118         int val=seg[seg[i].lson].val;
119         if(x<=val) return operator4(seg[i].lson,l,mid,x);
120         else return operator4(seg[i].rson,mid+1,r,x-val);
121     }
122 } AC;
123 
124 
125 int main()
126 {
127 
128     int m;
129     while(scanf("%d",&m)!=EOF)
130     {
131         int op,x,root,temp;
132         AC.init(root);
133         while(m--)
134         {
135             scanf("%d%d",&op,&x);
136             switch(op)
137             {
138             case 1:
139                 AC.ins(root,0,INF,x,1);
140                 break;
141             case 2:
142                 temp=AC.query(root,0,INF,0,x);
143                 AC.operator2(root,0,INF,x,temp);
144                 break;
145             case 3:
146                 temp=AC.query(root,0,INF,x,INF);
147                 AC.operator3(root,0,INF,x,temp);
148                 break;
149             case 4:
150                 printf("%d\n",AC.operator4(root,0,INF,x));
151                 break;
152             case 5:
153                 printf("%d\n",AC.query(root,0,INF,0,x-1));
154                 break;
155             }
156         }
157     }
158     return 0;
159 }

 


 

posted @ 2017-05-19 17:12  Code-dream  阅读(185)  评论(0编辑  收藏  举报