您的位置:首页 > 其它

值域线段树 (玲珑OJ 1117)

2017-05-19 17:12 465 查看
点击打开题目链接
题目意思很简单:

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

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

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

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;

typedef long long int LL;
const LL INF=1000000000;
const int maxn=6e6+100;

struct ACM
{
struct segment
{
int val,lson,rson;
bool mark;
} seg[maxn];
int sz;
/***
开辟新的节点并初始化
*/
int newnode()
{
sz++;
if(sz>=maxn)
{
int lzq=5,zhangpan=0;
lzq=lzq/zhangpan;

}
seg[sz].lson=seg[sz].rson=-1;
seg[sz].val=0,seg[sz].mark=false;
return sz;
}
/***
初始化根节点
*/
void init(int& root)
{
sz=-1;
root=newnode();
}
/***
标记下放操作,如果没有节点开辟新的节点;
*/
void pushdown(int i)
{
int l=seg[i].lson,r=seg[i].rson;
if(l==-1) seg[i].lson=newnode();
if(r==-1) seg[i].rson=newnode();
if(seg[i].mark)
{
seg[i].mark=false;
seg[l].mark=seg[r].mark=true;
seg[l].val=seg[r].val=0;
}
}
void pushup(int i)
{
int l=seg[i].lson,r=seg[i].rson;
seg[i].val=seg[l].val+seg[r].val;
}
/***
插入函数 ; 在 pos 位置上面加上 val;
*/
void ins(int i,int l,int r,int pos,int val)
{
if(l==r)
{
seg[i].val+=val;
return ;
}
pushdown(i);
int mid=(l+r)>>1;
if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
else ins(seg[i].rson,mid+1,r,pos,val);
pushup(i);
}
/***
将 L,R 这段区间上的值,更新为 0;
*/
void del(int i,int l,int r,int L,int R)
{
if(l==L&&r==R)
{
seg[i].val=0;
seg[i].mark=true;
return ;
}
pushdown(i);
int mid=(l+r)>>1;
if(R<=mid) del(seg[i].lson,l,mid,L,R);
else if(L>mid) del(seg[i].rson,mid+1,r,L,R);
else del(seg[i].lson,l,mid,L,mid),del(seg[i].rson,mid+1,r,mid+1,R);
pushup(i);
}
int find(int i,int l,int r,int x) //第x小的数字;
{
if(l==r) return l;
pushdown(i);
int lval=0;
int mid=(l+r)>>1;
if(seg[i].lson!=-1) lval=seg[seg[i].lson].val;
if(x<=lval) return find(seg[i].lson,l,mid,x);
else return find(seg[i].rson,mid+1,r,x-lval);
}
int query(int i,int l,int r,int L,int R) //区间 数的个数;
{
if(l==L&&r==R) return seg[i].val;
pushdown(i);
int mid=(l+r)>>1;
if(R<=mid) return query(seg[i].lson,l,mid,L,R);
else if(L>mid) return query(seg[i].rson,mid+1,r,L,R);
else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+1,r,mid+1,R);
}
} AC;

int main()
{
int m;
scanf("%d",&m);
int op,x,root,temp;
AC.init(root);
while(m--)
{
scanf("%d%d",&op,&x);
switch(op)
{
case 1:
AC.ins(root,0,INF,x,1);
break;
case 2:
temp=AC.query(root,0,INF,0,x);
AC.del(root,0,INF,0,x);
AC.ins(root,0,INF,x,temp);
break;
case 3:
temp=AC.query(root,0,INF,x,INF);
AC.del(root,0,INF,x,INF);
AC.ins(root,0,INF,x,temp);
break;
case 4:
printf("%d\n",AC.find(root,0,INF,x));
break;
case 5:
printf("%d\n",AC.query(root,0,INF,0,x-1));
break;
}
}
return 0;
}

代码二:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;

const int INF=1000000000;
const int maxn=6e6+100;
struct ACM
{
/***
对于 2,3 操作,先查询个数,再插入这个数字:
意思就是更新到底部,加上查询出来的个数;
并加上清零的标记;

*/
struct Node
{
int val,lson,rson;
bool mark;
} seg[maxn];
int sz;
int newnode()
{
sz++;
seg[sz].val=0;
seg[sz].lson=-1;
seg[sz].rson=-1;
seg[sz].mark=false;
return sz;
}
void init(int& root)
{
sz=-1;
root=newnode();
}
void pushdown(int i)
{
int l=seg[i].lson,r=seg[i].rson;
if(l==-1) seg[i].lson=newnode();
if(r==-1) seg[i].rson=newnode();
if(seg[i].mark)
{
seg[i].mark=false;
seg[l].mark=seg[r].mark=true;
seg[l].val=seg[r].val=0;
}
}
void pushup(int i)
{
int l=seg[i].lson,r=seg[i].rson;
seg[i].val=seg[l].val+seg[r].val;
}
int query(int i,int l,int r,int L,int R) //区间 数的个数;
{
if(l==L&&r==R) return seg[i].val;
pushdown(i);
int mid=(l+r)>>1;
if(R<=mid) return query(seg[i].lson,l,mid,L,R);
else if(L>mid) return query(seg[i].rson,mid+1,r,L,R);
else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+1,r,mid+1,R);
}
void ins(int i,int l,int r,int pos,int val)
{
if(l==r)
{
seg[i].val+=val;
return ;
}
pushdown(i);
int mid=(l+r)>>1;
if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
else ins(seg[i].rson,mid+1,r,pos,val);
pushup(i);
}
void operator2(int i,int l,int r,int x,int val)
{
if(l==r)
{
seg[i].val=val;
return ;
}
int mid=(l+r)>>1;
pushdown(i);
if(x<=mid) operator2(seg[i].lson ,l,mid,x,val);
else
{
seg[seg[i].lson].mark=true;
seg[seg[i].lson].val=0;//如果,存在加到某一边,不存在也需要开新的节点!!
operator2(seg[i].rson,mid+1,r,x,val);
}
pushup(i);
}
void operator3(int i,int l,int r,int x,int val)
{
if(l==r)
{
seg[i].val=val;
return ;
}
pushdown(i);
int mid=(l+r)>>1;
if(x<=mid)
{
seg[seg[i].rson].mark=true;
seg[seg[i].rson].val=0;
operator3(seg[i].lson,l,mid,x,val);
}
else operator3(seg[i].rson,mid+1,r,x,val);
pushup(i);
}
int operator4(int i,int l,int r,int x)
{
if(l==r) return l;
int mid=(l+r)>>1;
pushdown(i);
int val=seg[seg[i].lson].val;
if(x<=val) return operator4(seg[i].lson,l,mid,x);
else return operator4(seg[i].rson,mid+1,r,x-val);
}
} AC;

int main()
{

int m;
while(scanf("%d",&m)!=EOF)
{
int op,x,root,temp;
AC.init(root);
while(m--)
{
scanf("%d%d",&op,&x);
switch(op)
{
case 1:
AC.ins(root,0,INF,x,1);
break;
case 2:
temp=AC.query(root,0,INF,0,x);
AC.operator2(root,0,INF,x,temp);
break;
case 3:
temp=AC.query(root,0,INF,x,INF);
AC.operator3(root,0,INF,x,temp);
break;
case 4:
printf("%d\n",AC.operator4(root,0,INF,x));
break;
case 5:
printf("%d\n",AC.query(root,0,INF,0,x-1));
break;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: