题意:

有两种操作: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. Zepto v1.0-1源码注解

    /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ ;(funct ...

  2. stl(set和map)

    http://codeforces.com/gym/101911/problem/A Recently Monocarp got a job. His working day lasts exactl ...

  3. 物流运输(最短路+dp)

    这道题是相当的火,但是在tyher的讲解下我一遍就AC了!!! Part 1 理解题目 从第一天到最后一天,总会有一些点莫名其妙地走不了,所以导致我们不能按照上一次的最短路一直运输得到最少费用,而需要 ...

  4. 三种分布式锁 简易说说(包含前一篇提到的redis分布式锁)

    大多数互联网系统都是分布式部署的,分布式部署确实能带来性能和效率上的提升,但为此,我们就需要多解决一个分布式环境下,数据一致性的问题. 当某个资源在多系统之间,具有共享性的时候,为了保证大家访问这个资 ...

  5. THUPC/CTS/APIO2019划水记

    THUPC:划水的咸鱼 CTS:打铁 APIO:压线cu 终于又回归了文化课. 落下10天的课程,OI又得停一停了 这次划水,又见识了许多的神仙,再一次被吊打 5.11~5.20,有太多的事情需要回忆 ...

  6. 【转载】Spring bean 中 constructor-arg属性

    转载地址:https://blog.csdn.net/qq_27292113/article/details/78063696 方便以后查阅

  7. DTS

    一.DTS的加载过程   如果要使用Device Tree,首先用户要了解自己的硬件配置和系统运行参数,并把这些信息组织成Device Tree source file.通过DTC(Device Tr ...

  8. Nginx学习总结(一)

    Nginx是目前比较主流的HTTP反向代理服务器(其企业版提供了基于TCP层的反向代理插件),对于构建大型分布式web应用,具有举足轻重的作用.简单来说,nginx有2个主要的功能:动/静态资源分离. ...

  9. Thymeleaf入门——入门与基本概述

    https://www.cnblogs.com/jiangbei/p/8462294.html 一.概述 1.是什么 简单说, Thymeleaf 是一个跟 Velocity.FreeMarker 类 ...

  10. 微信小程序(10)--开发者工具更新以后wxss编译错误

    更新最新版微信开发者工具后,出现下面报错: 解决办法: 1.在控制台输入openVendor() ,确定Enter: 2.清除里面的wcc.exe  wcsc.exe : 3.重启开发者工具