值域线段树 (玲珑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 }