题意:

有两种操作:1.在[l,r]上插入一条值为val的线段 2.问p位置上值第k小的线段的值(是否存在)

特别的,询问的时候l和p合起来是一个递增序列

1<=l,r<=1e9;1<=val<=1e6; 1<=k<=1e9

思路:

因为l和p总体是递增的,第i个询问的p一定大于i之前所有操作的l,而前面能影响到i的答案的只有r>=p的线段。由此可以想到将l,r,p合起来离散化,从左往右扫描,遇到l,就在权值线段树上插入对应的val,遇到r就删除对应的val,而遇到询问时,当前的线段树必然对应了P点的所有线段,求一下全局第k小就能得到答案。

全局第k小除了利用权值线段树外,还能通过二分树状数组求得,复杂度比线段树多logn,但是实际测试好像还是树状数组快。

权值线段树

#include <bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxn=2e5+5;//离散化值可能有两倍
struct node {
int opt,p,val,id;
operator<(node b) {
if(p!=b.p)
return p<b.p;
else if(opt==2)
return true;
else if(b.opt==2)
return false;
else
return id<b.id;
}
} P[maxn];
int cnt=0,n;
int T[maxn<<2];
inline void push_now(int k){
T[k]=T[k<<1]+T[k<<1|1];
}
void add(int rt,int l,int r,int p,int val){//[l,r]
if(l==r){
T[rt]+=val;
return;
}
int mid=(l+r)>>1;
if(p<=mid) add(lson,l,mid,p,val);
if(p>mid) add(rson,mid+1,r,p,val);
push_now(rt);
}
int query(int rt,int l,int r,int k){
if(T[rt]<k) return -1;
if(l==r) return l;
int mid=(l+r)>>1;
if(T[lson]>=k)
return query(lson,l,mid,k);
else
return query(rson,mid+1,r,k-T[lson]);
}
int lisan[maxn],tot=0;
int ans[maxn],acnt=0;
int main() {
int t,E;
cin>>t;
for(int kase=1; kase<=t; kase++) {
scanf("%d",&E);
tot=0;acnt=0;cnt=0;
for(int i=1; i<=E; i++)
T[i]=0;
int x,val,y,opt;
for(int i=1; i<=E; i++) {
scanf("%d%d%d",&opt,&x,&val);
if(opt==1) {
lisan[++tot]=val;
scanf("%d",&y);
P[++cnt]= {1,x,val,i};
P[++cnt]= {-1,y,val,i};
} else {
P[++cnt]= {2,x,val,i};
}
}
sort(lisan+1,lisan+1+tot);
n=unique(lisan+1,lisan+1+tot)-(lisan+1);
for(int i=1; i<=cnt; i++) {
if(P[i].opt!=2)
P[i].val=lower_bound(lisan+1,lisan+1+n,P[i].val)-lisan;
}
sort(P+1,P+1+cnt);
for(int i=1; i<=cnt; i++) {
if(P[i].opt!=2) {
add(1,1,n,P[i].val,P[i].opt);
}
else {
int temp=query(1,1,n,P[i].val);
if(temp==-1)
ans[++acnt]=-1;
else
ans[++acnt]=lisan[temp];
}
}
printf("Case %d:\n",kase);
for(int i=1; i<=acnt; i++) {
printf("%d\n",ans[i]);
}
}
}

树状数组+二分

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;//离散化值可能有两倍
struct node {
int opt,p,val,id;
operator<(node b) {
if(p!=b.p)
return p<b.p;
else if(opt==2)
return true;
else if(b.opt==2)
return false;
else
return id<b.id;
}
} P[maxn];
int cnt=0,n;
int T[maxn];
int lowbit(int x) {
return x&(-x);
}
int getsum(int p) {
int res=0;
while(p>0) {
res+=T[p];
p-=lowbit(p);
}
return res;
}
void add(int p,int val) {
while(p<=n) {
T[p]+=val;
p+=lowbit(p);
}
}
int query(int x) {
int l=0,r=n,mid;
while(r-l>1) {
mid=(r+l+1)/2;
if(getsum(mid)>=x)
r=mid;
else
l=mid;
}
return r;
}
int lisan[maxn],tot=0;
int ans[maxn],acnt=0;
int main() {
int t,E;
cin>>t;
for(int kase=1; kase<=t; kase++) {
scanf("%d",&E);
tot=0;
acnt=0;
cnt=0;
for(int i=1; i<=E; i++)
T[i]=0;
int x,val,y,opt;
for(int i=1; i<=E; i++) {
scanf("%d%d%d",&opt,&x,&val);
if(opt==1) {
lisan[++tot]=val;
scanf("%d",&y);
P[++cnt]= {1,x,val,i};
P[++cnt]= {-1,y,val,i};
} else {
P[++cnt]= {2,x,val,i};
}
}
sort(lisan+1,lisan+1+tot);
n=unique(lisan+1,lisan+1+tot)-(lisan+1);
for(int i=1; i<=cnt; i++) {
if(P[i].opt!=2)
P[i].val=lower_bound(lisan+1,lisan+1+n,P[i].val)-lisan;
}
sort(P+1,P+1+cnt);
for(int i=1; i<=cnt; i++) {
if(P[i].opt!=2) {
add(P[i].val,P[i].opt);
}
else {
int temp=query(P[i].val);
if(getsum(n)<P[i].val)
ans[++acnt]=-1;
else
ans[++acnt]=lisan[temp];
}
}
printf("Case %d:\n",kase);
for(int i=1; i<=acnt; i++) {
printf("%d\n",ans[i]);
}
}
}

The Stream of Corning 2( 权值线段树/(树状数组+二分) )的更多相关文章

  1. 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

    谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...

  2. 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] D ...

  3. BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)

    题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...

  4. 动态求区间K大值(权值线段树)

    我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...

  5. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  6. 【BZOJ3685】【zkw权值线段树】普通van Emde Boas树

    原题传送门 因为马上要开始搞树套树了,所以学了一波权值线段树...毕竟是会点zkw线段树的,所以zkw线段树大法好! 解题思路: 介绍一下权值线段树吧,其实感觉就是线段树的本义,就是你用线段树维护了数 ...

  7. BZOJ_2161_布娃娃_权值线段树

    BZOJ_2161_布娃娃_权值线段树 Description 小时候的雨荨非常听话,是父母眼中的好孩子.在学校是老师的左右手,同学的好榜样.后来她成为艾利斯顿第二 代考神,这和小时候培养的良好素质是 ...

  8. BZOJ_3685_普通van Emde Boas树_权值线段树

    BZOJ_3685_普通van Emde Boas树_权值线段树 Description 设计数据结构支持: 1 x  若x不存在,插入x 2 x  若x存在,删除x 3    输出当前最小值,若不存 ...

  9. B20J_2733_[HNOI2012]永无乡_权值线段树合并

    B20J_2733_[HNOI2012]永无乡_权值线段树合并 Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些 ...

随机推荐

  1. 字符串类——KMP算法的应用

    1,字符串类中的新功能(本文代码已集成到字符串类——字符串类的创建(上)中,这里讲述函数实现原理): 2,子串查找(KMP 算法直接运用): 1,int indexOf(const char* s) ...

  2. P2009 跑步

    题目传送门 热烈庆祝SZM黄题破80,绿题破30,蓝题破20!!!(紫题还是2,,,,orz%%%) 非常水的一道最短路,小于等于100果断Floyd,要好好读题,别忘记特判,8分钟基本就能做出来啦~ ...

  3. Cnblogs 的 MetaWeblog 的接口发生了变化

    Cnblogs 的 MetaWeblog 的接口发生了变化 */--> Cnblogs 的 MetaWeblog 的接口发生了变化 最近把 emacs 重新配置了一下,把 cnblogs 包也重 ...

  4. Ecshop 商品详情页如何添加立即购买按钮

    1,加到位置 <li class="add_cart_li"> <a href="javascript:addToCart1({$goods.goods ...

  5. 如何写一个简单的基于 Qt 框架的 HttpServer ?

    httpserver.h #ifndef HTTPSERVER_H #define HTTPSERVER_H #include <QObject> #include <QtCore& ...

  6. bzoj2176 Strange string(字符串最小表示法)

    Time Limit: 10 Sec  Memory Limit: 259 MB 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的 ...

  7. 剑指offer学习--初级c++面试题

    定义一个空的类型,里面没有任何成员函数和成员变量,对该类型求sizeof,得到的结果是多少? 答案是1.空类型中的实例中不包含任何信息,本来求sizeof应该是0,但是当我们声明该类型的实例的时候,他 ...

  8. JS面向对象——原型模型

    以下通过一段示例代码,说明原型模型中的基本概念以及知识点. <!DOCTYPE html> <html> <head> <title>原型模型</ ...

  9. mysql官网下载安装

    1.官网下载zip压缩文件 2.解压到指定文件夹 3.配置环境变量 4.新建my.ini 5.管理员权限打开cmd命令行,mysqld install mysql,mysql --initialize ...

  10. Winfrom 弹出窗体位置设定

    Winfrom 窗体弹出位置设定,其实就是两种模式,第一种模式是通过Winform提供的属性来设定:第二种模式是自定义,可以相对于软件本身,也可以是相对于屏幕. 一.第一种模式 使用Winform提供 ...