3110: [Zjoi2013]K大数查询

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1384  Solved: 629
[Submit][Status]

Description

有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

Input

第一行N,M
接下来M行,每行形如1 a b c或2 a b c

Output

输出每个询问的结果

Sample Input

2 5
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3

Sample Output

1
2
1

HINT

【样例说明】

第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

大的数是 1 。‍

N,M<=50000,N,M<=50000

a<=b<=N

1操作中abs(c)<=N

2操作中abs(c)<=Maxlongint

  这道题本来想用线段树套平衡树做,但是即便加了永久lazy标记,还是TLE了,后来改为树状数组套线段树,注意树状数组二分可优化为O(logn)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXT 8100000
#define MAXN 51009
#define lch (now<<1)
#define rch (now<<1^1)
#define INF 0x3f3f3f3f
#define L(x) SBT[x].L
#define R(x) SBT[x].R
#define S(x) SBT[x].S
#define val(x) SBT[x].val
#define tot(x) SBT[x].tot
#define sum(x) SBT[x].sum
typedef long long qword;
int n,m;
inline int nextInt()
{
register int x=;
register char ch;
while (ch=getchar(),ch<''||ch > '');
do
x=x*+ch-'';
while (ch=getchar(),ch<='' && ch>='');
return x;
}
int topt;
struct SBT_T
{
int L,R,S,val,tot,sum;
}SBT[MAXT];
inline void update(int now)
{
if (!now)return ;
S(now)=S(L(now))+S(R(now))+;
sum(now)=sum(L(now))+sum(R(now))+tot(now);
}
inline void l_rotate(int &now)
{
register int t=R(now);
R(now)=L(t);update(now);
L(t)=now;update(t);
now=t;
}
inline void r_rotate(int &now)
{
register int t=L(now);
L(now)=R(t);update(now);
R(t)=now;update(t);
now=t;
}
inline void maintain(int &now)
{
if (S(L(L(now)))>S(R(now)))
{
r_rotate(now);
//maintain(L(now));
maintain(R(now));
maintain(now);
}else if (S(R(R(now)))>S(L(now)))
{
l_rotate(now);
//maintain(R(now));
maintain(L(now));
maintain(now);
}else if (S(R(L(now)))>S(R(now)))
{
l_rotate(L(now));
r_rotate(now);
maintain(R(now));
maintain(L(now));
maintain(now);
}else if (S(L(R(now)))>S(L(now)))
{
r_rotate(R(now));
l_rotate(now);
maintain(R(now));
maintain(L(now));
maintain(now);
}
}
void Insert(int &now,int v,int t)
{
if (!now)
{
// if (topt>MAXT-10)throw 1;
now=++topt;
L(now)=R(now)=;
val(now)=v;
tot(now)=sum(now)=t;
return ;
}
if (v==val(now))
tot(now)+=t;
else if (v<val(now))
Insert(L(now),v,t);
else if (val(now)<v)
Insert(R(now),v,t);
update(now);
maintain(now);
}
/*
int Get_tot(int &now,int v)
{
if (!now)return 0;
if (val(now)==v)
return sum(L(now));
else if (v<val(now))
return Get_tot(L(now),v);
else if (val(now)<v)
return Get_tot(R(now),v)+sum(L(now))+tot(now);
return 0;
}*/
int Get_tot(int now,int v)
{
int ret=;
while (now && val(now)!=v)
{
if (v<val(now))
now=L(now);
else if (val(now)<v)
ret+=sum(L(now))+tot(now),now=R(now);
}
if (now && val(now)==v)ret+=sum(L(now));
return ret;
}
void Scan(int now)
{
if (!now)return ;
Scan(L(now));
printf("%d(%d) ",val(now),tot(now));
Scan(R(now));
}
struct sgt_node
{
int l,r;
int rt;
int lazy;
}sgt[MAXN*];
void Build_sgt(int now,int l,int r)
{
sgt[now].l=l;
sgt[now].r=r;
if (l==r)return ;
Build_sgt(lch,l,(l+r)>>);
Build_sgt(rch,((l+r)>>)+,r);
}
void Add_val(int now,int l,int r,int v)
{
Insert(sgt[now].rt,v,r-l+);
if (sgt[now].l==l && sgt[now].r==r)
{
Insert(sgt[now].lazy,v,);
return ;
}
int mid=(sgt[now].l+sgt[now].r)>>;
if (r<=mid)
{
Add_val(lch,l,r,v);
}else if (mid<l)
{
Add_val(rch,l,r,v);
}else
{
Add_val(lch,l,mid,v);
Add_val(rch,mid+,r,v);
}
}
int Qry_tot(int now,int l,int r,int v)
{
int ret=;
if (sgt[now].l==l && sgt[now].r==r)
{
return Get_tot(sgt[now].rt,v);
}
ret=Get_tot(sgt[now].lazy,v)*(r-l+);
int mid=(sgt[now].l+sgt[now].r)>>;
if (r<=mid)
ret+=Qry_tot(lch,l,r,v);
else if (mid<l)
ret+=Qry_tot(rch,l,r,v);
else
ret+=Qry_tot(lch,l,mid,v)+Qry_tot(rch,mid+,r,v);
return ret;
}
int Get_size(int now,int l,int r)
{
if (sgt[now].l==l && sgt[now].r==r)
{
return sum(sgt[now].rt);
}
int mid=(sgt[now].l+sgt[now].r)>>;
if (r<=mid)
return Get_size(lch,l,r) + sum(sgt[now].lazy)*(r-l+);
else if (mid<l)
return Get_size(rch,l,r) + sum(sgt[now].lazy)*(r-l+);
else
return Get_size(lch,l,mid)+Get_size(rch,mid+,r) + sum(sgt[now].lazy)*(r-l+);
}
int Qry_kth(int ll,int rr,int rk)
{
int l,r,mid;
l=-n;
r=n+;
rk=Get_size(,ll,rr)-rk;
int t=;
if (rk<)return ;
while (l+<r)
{
mid=(l+r)/;
t=Qry_tot(,ll,rr,mid);
if (t<=rk)
l=mid;
else
r=mid;
}
return l;
} int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int i,j,k,x,y,z;
int rt=;
scanf("%d%d",&n,&m);
int opt;
Build_sgt(,,n);
for (i=;i<m;i++)//
{
opt=nextInt();
x=nextInt();
y=nextInt();
z=nextInt();
//scanf("%d%d%d%d",&opt,&x,&y,&z);
if (opt==)
{
Add_val(,x,y,z);
}else
{
printf("%d\n",Qry_kth(x,y,z));
}
}
}

线段树+SBT

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 101000
#define MAXT 28000000
#define lowbit(x) (x&(-x))
inline int nextInt()
{
register int x=;
register char ch;
while (ch=(char)getchar(),ch<''||ch > '');
do
x=x*+ch-'';
while (ch=(char)getchar(),ch<='' && ch>='');
return x;
} int n,m;
struct sgt_node
{
int lch,rch;
int t,lazy;
}sgt[MAXT];
int topt=;
void Add_sgt(int &now,int l,int r,int x,int y)
{
if (!now)
{
now=++topt;
sgt[now].t=sgt[now].lazy=;
}
if (l==x && r==y)
{
sgt[now].t+=r-l+;
sgt[now].lazy++;
return ;
}
int mid=(l+r)>>;
if (sgt[now].lazy)
{
if (!sgt[now].lch)
sgt[now].lch=++topt;
if (!sgt[now].rch)
sgt[now].rch=++topt;
sgt[sgt[now].lch].lazy+=sgt[now].lazy;
sgt[sgt[now].rch].lazy+=sgt[now].lazy;
sgt[sgt[now].lch].t+=sgt[now].lazy*(mid-l+);
sgt[sgt[now].rch].t+=sgt[now].lazy*(r-mid);
sgt[now].lazy=;
}
if (y<=mid)
{
Add_sgt(sgt[now].lch,l,mid,x,y);
}else if (mid<x)
{
Add_sgt(sgt[now].rch,mid+,r,x,y);
}else
{
Add_sgt(sgt[now].lch,l,mid,x,mid);
Add_sgt(sgt[now].rch,mid+,r,mid+,y);
}
sgt[now].t=sgt[sgt[now].lch].t+sgt[sgt[now].rch].t;
}
int Qry_sgt(int &now,int l,int r,int x,int y)
{
if (!now || sgt[now].t==)return ;
if (l==x && r==y)
return sgt[now].t;
int mid=(l+r)>>;
if (sgt[now].lazy)
{
if (!sgt[now].lch)
sgt[now].lch=++topt;
if (!sgt[now].rch)
sgt[now].rch=++topt;
sgt[sgt[now].lch].lazy+=sgt[now].lazy;
sgt[sgt[now].rch].lazy+=sgt[now].lazy;
sgt[sgt[now].lch].t+=sgt[now].lazy*(mid-l+);
sgt[sgt[now].rch].t+=sgt[now].lazy*(r-mid);
sgt[now].lazy=;
}
if (y<=mid)
{
return Qry_sgt(sgt[now].lch,l,mid,x,y);
}else if (mid<x)
{
return Qry_sgt(sgt[now].rch,mid+,r,x,y);
}else
{
return Qry_sgt(sgt[now].lch,l,mid,x,mid)
+Qry_sgt(sgt[now].rch,mid+,r,mid+,y);
}
}
int tarr2[MAXN],tarr3[MAXN];
void Add_tarr2(int l,int r)
{
r++;
int a=r;
while (r<MAXN)
{
tarr2[r]--;
tarr3[r]-=a;
r+=lowbit(r);
}
a=l;
while (l<MAXN)
{
tarr2[l]++;
tarr3[l]+=a;
l+=lowbit(l);
}
}
//segma((n-i+1)*a[i])
//=(n+1)*segma(a[i]) - segma(i*a[i])
int Qry_tarr2(int l,int r)
{
int ret=;
int v1,v2;
int now;
v1=;
l--;
now=r;
v1=v2=;
while (now)
{
v1+=tarr2[now];
v2+=tarr3[now];
now-=lowbit(now);
}
ret+=v1*(r+)-v2;
now=l;
v1=v2=;
while (now)
{
v1+=tarr2[now];
v2+=tarr3[now];
now-=lowbit(now);
}
ret-=v1*(l+)-v2;
return ret;
}
int tarr[MAXN];
void Add_tarr(int pos,int l,int r)
{
pos+=n+;
Add_tarr2(l,r);
while (pos<MAXN)
{
Add_sgt(tarr[pos],,n+,l,r);
pos+=lowbit(pos);
}
}
/*
int Qry_tarr(int rk,int ll,int rr)
{
int now=0,t;
int i;
int l,r,mid;
rk=Qry_tarr2(ll,rr)-rk+1;
l=-n-1;r=n+1;
while (l+1<r)
{
t=0;
mid=(l+r)>>1;
now=mid+n+1;
while (now)
{
t+=Qry_sgt(tarr[now],0,n+1,ll,rr);
now-=lowbit(now);
}
if (t<rk)
l=mid;
else
r=mid;
}
return r==-n ? 1 : r;
}*/
int Qry_tarr(int rk,int ll,int rr)
{
int now=,t;
int i;
int l,r,mid;
rk=Qry_tarr2(ll,rr)-rk+;
for (i=;i>=;i--)
{
if (now+(<<i)<MAXN && (t=Qry_sgt(tarr[now+(<<i)],,n+,ll,rr))<rk)
{
rk-=t;
now+=(<<i);
}
}
now=now+-(n+);
return now;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
scanf("%d%d",&n,&m);
int i;
int opt,x,y,z;
for (i=;i<m;i++)
{
opt=nextInt();
x=nextInt();
y=nextInt();
z=nextInt();
//scanf("%d%d%d%d",&opt,&x,&y,&z);
if (opt==)
{
Add_tarr(z,x,y);
}else
{
printf("%d\n",Qry_tarr(z,x,y));
}
}
}

树状数组+线段树

bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树的更多相关文章

  1. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  2. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  3. BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...

  4. BZOJ 1901 Zju2112 Dynamic Rankings 树状数组套线段树

    题意概述:带修改求区间第k大. 分析: 我们知道不带修改的时候直接上主席树就可以了对吧?两个版本号里面的节点一起走在线段树上二分,复杂度是O((N+M)logN). 然而这里可以修改,主席树显然是凉了 ...

  5. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  6. 【序列操作IV】树状数组套线段树/树套树

    题目描述 给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作. 1. ai(1≤i≤n)变成 x(0≤x≤109). 2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1 ...

  7. [APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树)

    [APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树) 题面 略 分析 首先把一组询问(x,y)看成二维平面上的一个点,我们想办法用数据结构维护这个二维平面(注意根据题意这 ...

  8. P3157 [CQOI2011]动态逆序对(树状数组套线段树)

    P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...

  9. 2019南昌网络赛  I. Yukino With Subinterval 树状数组套线段树

    I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...

随机推荐

  1. NYOJ 38 布线问题_(解法2 Prim算法)

    时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 南阳理工学院要进行用电线路改造.如今校长要求设计师设计出一种布线方式.该布线方式须要满足下面条件: 1.把全部的楼都供 ...

  2. jsp-javabean-setproperty介绍

    李兴华<java web开发实战经典>第7章关于javabean的讲解中说道:<jsp:setProperty>标签一共有4种使用方法·下面列出了4种操作语法的格式:   设置 ...

  3. 重新格式化namenode后,出现java.io.IOException Incompatible clusterIDs

    错误: java.io.IOException: Incompatible clusterIDs in /data/dfs/data: namenode clusterID = CID-d1448b9 ...

  4. hadoop错误ERROR namenode.NameNode (NameNode.javamain(1657)) - Failed to start namenode java.net.BindException:Port in use:host1:50070

    解决方法: 1.通过lsof -i:50070(lsof可以通过yum install lsof安装)查看,发现是mysql被占用了 2.修改mysql端口 从/usr/share/mysql/my- ...

  5. DS_Store

    .DS_Store (英文全称 Desktop Services Store)[1] 是一种由苹果公司的Mac OS X操作系统所创造的隐藏文件,目的在于存贮文件夹的自定义属性,例如文件们的图标位置或 ...

  6. xmemcached user guide --存档

    XMemcached Introduction XMemcached is a new java memcached client. Maybe you don't know "memcac ...

  7. Java基础知识强化之IO流笔记35:InputStreamReader(Reader字符流的子类)2种read数据方式

    1. InputStreamReader(Reader字符流的子类)2种read数据方式: InputStreamReader的read方法: int read():一次读取一个字符 int read ...

  8. Xcode4快速Doxygen文档注释 — 简明图文教程

    转自:http://blog.csdn.net/totogo2010/article/details/9100767 准备2个文件: 文件一,ThisService.app 文件二,Doxygen.r ...

  9. 【原】window上安装elasticserach

    [window上安装elasticserach] 系统环境:2008R2 x64测试安装用的服务器IP:192.168.12.52elasticsearch版本:2.3.4JDK版本:jdk 1.8. ...

  10. SELECT [Code] ,[AlarmID] ,[ItemName] ,[isDeleted] ,[Remark] FROM [LjlData].[dbo].[T_BaseDetail] union select 0--

    SELECT  [id]       ,[AlarmID]       ,[ItemName]       ,[isDeleted]       ,[Remark]   FROM [LjlData]. ...