bzoj 3110 [Zjoi2013]K大数查询(树套树)
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
1 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
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大数查询(树套树)的更多相关文章
- BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)
题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...
- BZOJ 3110: [Zjoi2013]K大数查询 [树套树]
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6050 Solved: 2007[Submit][Sta ...
- 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 & 3236 [Ahoi2013] 作业 题解
[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 978 Solved: 476 Descri ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )
BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ---------------------------------------------------- ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
- BZOJ 3110 [Zjoi2013]K大数查询(整体二分)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 11654 Solved: 3505[Submit][St ...
- bzoj 3110 [Zjoi2013]K大数查询【树套树||整体二分】
树套树: 约等于是个暴力了.以区间线段树的方式开一棵权值线段树,在权值线段树的每一个点上以动态开点的方式开一棵区间线段树. 结果非常惨烈(时限20s) #include<iostream> ...
- BZOJ 3110 [Zjoi2013]K大数查询 ——树套树
[题目分析] 外层区间线段树,内层是动态开点的权值线段树. SY神犇说树套树注重的是内外层的数据结构的选择问题,果然很重要啊. 动态开点的实现方法很好. [代码] #include <cstdi ...
- BZOJ 3110: [Zjoi2013]K大数查询 [整体二分]
有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. N ...
随机推荐
- leetcode 练习1 two sum
leetcode 练习1 two sum whowhoha@outlook.com 问题描述 Given an array of integers, return indices of the tw ...
- uva 11069
一开始打了个表 发现 a[i] = a[i-3]+a[i-2]; #include <iostream> #include <fstream> #include <cs ...
- spoj 394
每段可以连续的串的可能性是个Fibonacci数列 但是直接dp更好吧~~ #include <cstdio> #include <cstring> using names ...
- js检测浏览器版本代码,兼容ie11
原文:http://blog.csdn.net/tenkin/article/details/11640165 <script type="text/javascript"& ...
- CURL与PHP-CLI的应用【CLI篇】
CLI的普通应用 什么是PHP-CLI php-cli是php Command Line Interface的简称,即PHP命令行接口,在windows和linux下都是支持PHP-CLI模式的; 为 ...
- std::remove
#include <algorithm> template< class ForwardIt, class T > ForwardIt remove( ForwardIt fi ...
- Android TabHost中实现标签的滚动以及一些TabHost开发的奇怪问题
最近在使用TabHost的时候遇到了一些奇怪的问题,在这里总结分享备忘一下. 首先说一点TabActivity将会被FragmentActivity所替代,但是本文中却是使用的TabActivity. ...
- Django用户认证系统(三)组与权限
Django的权限系统很简单,它可以赋予users或groups中的users以权限. Django admin后台就使用了该权限系统,不过也可以用到你自己的代码中. User对象具有两个ManyTo ...
- python中os模块path.abspath()返回的并不是绝对值,而是个错误的不存在的拼接地址
附截图: 当前路径: a=r'D:\PCsync\python\commands' 为绝对路径 遍历出来的4条应该是D:\PCsync\python\commands\commands.py... ...
- bzoj1385: [Baltic2000]Division expression
欧几里得算法.可以发现规律,a[2]作为分母,其他作为分子,必定是最好的选择.判断是否为整数即可. #include<cstdio> #include<cstring> #in ...