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

【思路】

线段树套线段树

里面的线段树基于区间,外面的线段树基于权值。我们就可以知道权值在[a,b]内且位置位于[c,d]内的数有多少个。

Add操作:在外面的线段树中找到c,将路径上经过的所有点对应的内层线段树区间[a,b]加1。

Query操作:在外面的线段树中通过询问对应的内层线段树结点的多少进行类似平衡树的转移。

线段树动态分配节点。

求第k大。。。

【代码】

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = +;
const int M = +; struct Tnode{
int lc,rc,add,sum;
Tnode(){}
}T[M]; int read() {
char c=getchar();
int f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} int n,m,sz;
int rt[M]; void pushdown(int u,int l,int r)
{
if(!T[u].add || l==r) return ;
if(!T[u].lc) T[u].lc=++sz;
if(!T[u].rc) T[u].rc=++sz;
int v=T[u].add , mid=(l+r)>>;
T[T[u].lc].add+=v;
T[T[u].rc].add+=v;
T[T[u].lc].sum+=v*(mid-l+);
T[T[u].rc].sum+=v*(r-mid);
T[u].add=;
}
void update(int &u,int l,int r,int L,int R)
{
if(!u) u=++sz;
pushdown(u,l,r);
if(L<=l&&r<=R) {
T[u].add++;
T[u].sum+=r-l+;
} else {
int mid=(l+r)>>;
if(L<=mid) update(T[u].lc,l,mid,L,R);
if(mid<R ) update(T[u].rc,mid+,r,L,R);
T[u].sum=T[T[u].lc].sum+T[T[u].rc].sum;
}
}
int query(int u,int l,int r,int L,int R)
{
if(!u) return ;
pushdown(u,l,r);
if(L<=l&&r<=R) return T[u].sum;
else {
int mid=(l+r)>>,ans=;
if(L<=mid) ans+=query(T[u].lc,l,mid,L,R);
if(mid<R ) ans+=query(T[u].rc,mid+,r,L,R);
return ans;
}
}
void change(int a,int b,int c)
{
int u=,l=,r=n;
while(l!=r) {
int mid=(l+r)>>;
update(rt[u],,n,a,b);
if(c<=mid) r=mid,u=u<<;
else l=mid+,u=u<<|;
}
update(rt[u],,n,a,b);
}
int query(int a,int b,int c)
{
int u=,l=,r=n;
while(l!=r) {
int mid=(l+r)>>;
int t=query(rt[u<<],,n,a,b);
if(c<=t) r=mid,u=u<<;
else l=mid+,u=u<<|,c-=t;
}
return l;
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
n=read(),m=read();
int op,a,b,c;
FOR(i,,m) {
op=read(),a=read(),b=read(),c=read();
if(op==) {
change(a,b,n-c+);
} else {
printf("%d\n",n-query(a,b,c)+);
}
}
return ;
}

bzoj 3110 [Zjoi2013]K大数查询(树套树)的更多相关文章

  1. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  2. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  3. 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

    [原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 Descri ...

  4. bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Stat ...

  5. BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )

    BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ---------------------------------------------------- ...

  6. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

  7. BZOJ 3110 [Zjoi2013]K大数查询(整体二分)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 11654  Solved: 3505[Submit][St ...

  8. bzoj 3110 [Zjoi2013]K大数查询【树套树||整体二分】

    树套树: 约等于是个暴力了.以区间线段树的方式开一棵权值线段树,在权值线段树的每一个点上以动态开点的方式开一棵区间线段树. 结果非常惨烈(时限20s) #include<iostream> ...

  9. BZOJ 3110 [Zjoi2013]K大数查询 ——树套树

    [题目分析] 外层区间线段树,内层是动态开点的权值线段树. SY神犇说树套树注重的是内外层的数据结构的选择问题,果然很重要啊. 动态开点的实现方法很好. [代码] #include <cstdi ...

  10. BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]

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

随机推荐

  1. PAT-乙级-1033. 旧键盘打字(20)

    1033. 旧键盘打字(20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 旧键盘上坏了几个键,于是在敲一段文 ...

  2. The 5th Zhejiang Provincial Collegiate Programming Contest---ProblemG:Give Me the Number

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2971 题意:将输入的英文数字表达转化为阿拉伯数字. #include< ...

  3. ASP + ACCESS 上传图片到数据库与将图片读出数据库显示之实现

    1.uppic.asp:上传图片程序 <% dim rs dim formsize,formdata,bncrlf,divider,datastart,dataend,mydata formsi ...

  4. POJ1151+线段树+扫描线

    /* 线段树+扫描线+离散化 求多个矩形的面积 */ #include<stdio.h> #include<string.h> #include<stdlib.h> ...

  5. mac 升级后 web 服务器起不来 问题

    4. Apache 要本地调试代码的时候发现Apache也不能幸免地跪了.执行apachectl -v发现Apache已经更新到2.4.9版本了.一定又是因为版本更新出了什么差错. 4.1 修改htt ...

  6. PHP的执行原理/执行流程

    http://www.cnblogs.com/hongfei/archive/2012/06/12/2547119.html 更深入的学习和了解可以查看下面: 风雨的博客http://www.laru ...

  7. MyBatis之传入参数parameterType

    在MyBatis的select.insert.update.delete这些元素中都提到了parameterType这个属性.MyBatis现在可以使用的parameterType有基本数据类型和Ja ...

  8. js 中map的几种实现方式

    简单使用 1, 通过对象方式: var myHash = {}; myHash["deviceID"] = "HY_000001"; myHash[" ...

  9. sizeof运算符来获取各种数据类型在内存中所占字节数--gyy整理

    C++并没有规定各种数据类型在内存中的存储大小,依赖于不同的编译器的不同而不同,要想获知当前编译器对各种数据类型分配的大小,可以通过sizeof运算符来获取. 使用方法1: sizeof(数据类型) ...

  10. 二维图形的矩阵变换(三)——在WPF中的应用矩阵变换

    原文:二维图形的矩阵变换(三)--在WPF中的应用矩阵变换 UIElement和RenderTransform 首先,我们来看看什么样的对象可以进行变换.在WPF中,用于呈现给用户的对象的基类为Vis ...