点击打开题目链接

题目意思很简单:

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=;
const int maxn=6e6+; struct ACM
{
struct segment
{
int val,lson,rson;
bool mark;
} seg[maxn];
int sz;
/***
开辟新的节点并初始化
*/
int newnode()
{
sz++;
if(sz>=maxn)
{
int lzq=,zhangpan=;
lzq=lzq/zhangpan; }
seg[sz].lson=seg[sz].rson=-;
seg[sz].val=,seg[sz].mark=false;
return sz;
}
/***
初始化根节点
*/
void init(int& root)
{
sz=-;
root=newnode();
}
/***
标记下放操作,如果没有节点开辟新的节点;
*/
void pushdown(int i)
{
int l=seg[i].lson,r=seg[i].rson;
if(l==-) seg[i].lson=newnode();
if(r==-) 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=;
}
}
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)>>;
if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
else ins(seg[i].rson,mid+,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=;
seg[i].mark=true;
return ;
}
pushdown(i);
int mid=(l+r)>>;
if(R<=mid) del(seg[i].lson,l,mid,L,R);
else if(L>mid) del(seg[i].rson,mid+,r,L,R);
else del(seg[i].lson,l,mid,L,mid),del(seg[i].rson,mid+,r,mid+,R);
pushup(i);
}
int find(int i,int l,int r,int x) //第x小的数字;
{
if(l==r) return l;
pushdown(i);
int lval=;
int mid=(l+r)>>;
if(seg[i].lson!=-) lval=seg[seg[i].lson].val;
if(x<=lval) return find(seg[i].lson,l,mid,x);
else return find(seg[i].rson,mid+,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)>>;
if(R<=mid) return query(seg[i].lson,l,mid,L,R);
else if(L>mid) return query(seg[i].rson,mid+,r,L,R);
else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+,r,mid+,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 :
AC.ins(root,,INF,x,);
break;
case :
temp=AC.query(root,,INF,,x);
AC.del(root,,INF,,x);
AC.ins(root,,INF,x,temp);
break;
case :
temp=AC.query(root,,INF,x,INF);
AC.del(root,,INF,x,INF);
AC.ins(root,,INF,x,temp);
break;
case :
printf("%d\n",AC.find(root,,INF,x));
break;
case :
printf("%d\n",AC.query(root,,INF,,x-));
break;
}
}
return ;
}

代码二:

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std; const int INF=;
const int maxn=6e6+;
struct ACM
{
/***
对于 2,3 操作,先查询个数,再插入这个数字:
意思就是更新到底部,加上查询出来的个数;
并加上清零的标记; */
struct Node
{
int val,lson,rson;
bool mark;
} seg[maxn];
int sz;
int newnode()
{
sz++;
seg[sz].val=;
seg[sz].lson=-;
seg[sz].rson=-;
seg[sz].mark=false;
return sz;
}
void init(int& root)
{
sz=-;
root=newnode();
}
void pushdown(int i)
{
int l=seg[i].lson,r=seg[i].rson;
if(l==-) seg[i].lson=newnode();
if(r==-) 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=;
}
}
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)>>;
if(R<=mid) return query(seg[i].lson,l,mid,L,R);
else if(L>mid) return query(seg[i].rson,mid+,r,L,R);
else return query(seg[i].lson,l,mid,L,mid)+query(seg[i].rson,mid+,r,mid+,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)>>;
if(pos<=mid) ins(seg[i].lson,l,mid,pos,val);
else ins(seg[i].rson,mid+,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)>>;
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=;//如果,存在加到某一边,不存在也需要开新的节点!!
operator2(seg[i].rson,mid+,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)>>;
if(x<=mid)
{
seg[seg[i].rson].mark=true;
seg[seg[i].rson].val=;
operator3(seg[i].lson,l,mid,x,val);
}
else operator3(seg[i].rson,mid+,r,x,val);
pushup(i);
}
int operator4(int i,int l,int r,int x)
{
if(l==r) return l;
int mid=(l+r)>>;
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+,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 :
AC.ins(root,,INF,x,);
break;
case :
temp=AC.query(root,,INF,,x);
AC.operator2(root,,INF,x,temp);
break;
case :
temp=AC.query(root,,INF,x,INF);
AC.operator3(root,,INF,x,temp);
break;
case :
printf("%d\n",AC.operator4(root,,INF,x));
break;
case :
printf("%d\n",AC.query(root,,INF,,x-));
break;
}
}
}
return ;
}

值域线段树 (玲珑OJ 1117)的更多相关文章

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

    1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...

  2. BZOJ 3218(a + b Problem-二分图套值域线段树)

    出这题的人是怎么想出来的…… 言归正传,这题是二分图套值域线段树. 首先经过 @Vfleaking的神奇建图后,把图拆成二分图, 不妨利用有向图最小割的性质建图(以前我一直以为最小割和边的方向无关,可 ...

  3. [BZOJ3065]带插入区间K小值 解题报告 替罪羊树+值域线段树

    刚了一天的题终于切掉了,数据结构题的代码真**难调,这是我做过的第一道树套树题,做完后感觉对树套树都有阴影了......下面写一下做题记录. Portal Gun:[BZOJ3065]带插入区间k小值 ...

  4. 值域线段树 bzoj 4627

    这是题目链接4627: [BeiJing2016]回转寿司 题目大意: 给定n个数,求有多少个字段和在 满足 L<=sum<=R; 解题思路 需要解这个题目,需要有线段树加可持续化的思想, ...

  5. Permutation UVA - 11525(值域树状数组,树状数组区间第k大(离线),log方,log)(值域线段树第k大)

    Permutation UVA - 11525 看康托展开 题目给出的式子(n=s[1]*(k-1)!+s[2]*(k-2)!+...+s[k]*0!)非常像逆康托展开(将n个数的所有排列按字典序排序 ...

  6. 51nod1394 差和问题 值域线段树

    水题..... 插入一个值$v$时,对于$[0, v - 1]$和$[v + 1, inf]$的点分别考虑就行了 删除相当于减去插入的贡献 用动态开点线段树卡点常数就过去了 复杂度$O(n \log ...

  7. bzoj 4627 值域线段树

    4627: [BeiJing2016]回转寿司 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 523  Solved: 227[Submit][Sta ...

  8. 牛客OI周赛10-提高组:B-Taeyeon的困惑(值域线段树)

    做法 单点加单点删,在值域线段树上直接二分就能求值前\(K\)小的和 Code #include<bits/stdc++.h> typedef long long LL; const LL ...

  9. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

随机推荐

  1. flex操作XML,强力总结帖

    初始化XML对象 XML对象可以代表一个XML元素.属性.注释.处理指令或文本元素.在ActionScript 3.0中我们可以直接将XML数据赋值给变量: var myXML:XML =    &l ...

  2. javascript变量初始化位置

    变量在之前<script type="text/javascript"></script>(或引用的js文件)中初始化,可以正常访问. 运行程序:弹出123 ...

  3. 【转载】Web Service和WCF的到底有什么区别

    [1]Web Service:严格来说是行业标准,也就是Web Service 规范,也称作WS-*规范,既不是框架,也不是技术. 它有一套完成的规范体系标准,而且在持续不断的更新完善中. 它使用XM ...

  4. POCO类

    我认为POCO(简单传统CLR对象)重点应该是简单,不跟其他不相关的类进行关联关系或不相关的属性.<NHibernate 4 Beginner Guid>这本书有提到,应该是满足下面三个条 ...

  5. Java Base64加密、解密原理Java代码(转载)

    博客来源:http://blog.csdn.net/songylwq/article/details/7578905 Base64是什么: Base64是网络上最常见的用于传输8Bit字节代码的编码方 ...

  6. 搭建mysql主从集群的步骤

    前提条件是:须要在linux上安装4个mysql数据库,都须要配置完对应的信息. 须要搭建: mysql 01: 主数据库  master                  mysql 02 :   ...

  7. WPF3.5 使用BINDINGGROUP进行实体类和集合验证

    前文介绍了自定义或系统自带的ValidationRule进行验证,这种方法对于单个元素的验证不错.很多时候,我们需要对表单(Form)进行验证,也就是对一个实体类进行验证,或者对一个集合的每项进行验证 ...

  8. Vmware虚拟机安装XP系统

    刚开始下载的雨林木风ghost镜像,首先是虚拟机无法自动识别系统版本.然后启动的时候也是无法从光驱启动,又接连下载了几个版本的系统镜像, 都是ghost的,都不好使,百度,偶然发现有人提了一句,需要用 ...

  9. 2016/08/11 Thinkphp之getField用法总结

    getField方法是ThinkPHP中用来获取字段值的方法,区别于select和find方法,通常仅用于获取个别字段的值.但是事实上并没有那么简单,该方法的用法总结如下: 获取某个字段值 这个是ge ...

  10. 开源流媒体播放器EasyPlayer

    配套开源流媒体服务器EasyDarwin,我们开发了一款开源的流媒体播放器EasyPlayer(现在已经升级合并到开源EasyClient中):同样,EasyPlayer目前只支持RTSP流媒体协议, ...