BZOJ3110 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操作中c<=Maxlongint
题解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define fo(i,x,y) for (int i = (x); i <= (y); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 400005,maxm = 20000005,INF = 1000000000; inline int read(){
int out = 0,flag = 1;char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
return out * flag;
} int a,b,c,N;
int n,m,siz = 0;
int rt[maxn];
int ls[maxm],rs[maxm],sum[maxm],lazy[maxm],L,R; inline void pd(int u,int l,int r){
if (!lazy[u] || l == r) return;
if (!ls[u]) ls[u] = ++siz;
if (!rs[u]) rs[u] = ++siz;
lazy[ls[u]] += lazy[u]; lazy[rs[u]] += lazy[u];
int mid = l + r >> 1;
sum[ls[u]] += lazy[u] * (mid - l + 1);
sum[rs[u]] += lazy[u] * (r - mid);
lazy[u] = 0;
} void modify(int& u,int l,int r){
if (!u) u = ++siz;
if (l >= L && r <= R){
sum[u] += (r - l + 1);
lazy[u]++;
}else {
pd(u,l,r);
int mid = l + r >> 1;
if (mid >= L) modify(ls[u],l,mid);
if (mid < R) modify(rs[u],mid + 1,r);
sum[u] = sum[ls[u]] + sum[rs[u]];
}
} int Query(int u,int l,int r){
if (!u) return 0;
if (l >= L && r <= R) return sum[u];
else {
pd(u,l,r);
int mid = l + r >> 1;
if (mid >= R) return Query(ls[u],l,mid);
else if (mid < L) return Query(rs[u],mid + 1,r);
else return Query(ls[u],l,mid) + Query(rs[u],mid + 1,r);
}
} inline void insert(){
int u = 1,l = 1,r = N;
L = a; R = b;
while (l < r){
int mid = l + r >> 1;
modify(rt[u],1,n);
if (c <= mid) r = mid,u = u << 1;
else l = mid + 1,u = u << 1 | 1;
}
modify(rt[u],1,n);
} inline void solve(){
int u = 1,l = 1,r = N,t;
L = a; R = b;
while (l < r){
int mid = l + r >> 1;
t = Query(rt[u << 1],1,n);
if (c <= t) r = mid,u = u << 1;
else l = mid + 1,u = u << 1 | 1,c -= t;
}
printf("%d\n",N - l + 1 - n);
} int main()
{
int cmd;
n = read(); m = read();N = n * 2 + 1;
while (m--){
cmd = read(); a = read(); b = read(); c = read();
if (cmd & 1){
c += n;
c = N - c + 1;
insert();
}else solve();
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define fo(i,x,y) for (int i = (x); i <= (y); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 1000000000;
//begin 18:00 end 19:27
inline int read(){
int out = 0,flag = 1;char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
return out * flag;
} int n,M; struct node{
int l,r,v,p,id,k;
}e[maxn]; inline bool cmp(const node& a,const node& b){
return a.k == b.k ? a.id < b.id : a.k < b.k;
} int ans[maxn];
int sum[4 * maxn],lazy[4 * maxn],L,R;
bool cl[4 * maxn]; inline void pd(int u,int l,int r){
if (cl[u]) sum[u<<1] = sum[u<<1|1] = lazy[u<<1] = lazy[u<<1|1] = cl[u] = 0,cl[u<<1] = cl[u<<1|1] = true;
if (lazy[u]){
int mid = l + r >> 1;
sum[u<<1] += (mid - l + 1) * lazy[u];
sum[u<<1|1] += (r - mid) * lazy[u];
lazy[u<<1] += lazy[u];
lazy[u<<1|1] += lazy[u];
lazy[u] = 0;
}
} inline void update(int u,int l,int r){
pd(u,l,r);
if (l >= L && r <= R){
sum[u] += (r - l + 1);
lazy[u]++;
}
else {
int mid = l + r >> 1;
if (mid >= L) update(u<<1,l,mid);
if (mid < R) update(u<<1|1,mid + 1,r);
sum[u] = sum[u<<1] + sum[u<<1|1];
}
} inline int Query(int u,int l,int r){
pd(u,l,r);
if (l >= L && r <= R) return sum[u];
else {
int mid = l + r >> 1;
if (mid >= R) return Query(u<<1,l,mid);
else if (mid < L) return Query(u<<1|1,mid + 1,r);
else return Query(u<<1,l,mid) + Query(u<<1|1,mid + 1,r);
}
} void solve(int l,int r,int el,int er){
if (el > er) return;
if (l == r){
for (int i = el; i <= er; i++)
if (e[i].p == 2) ans[e[i].id] = l;
}
else {
cl[1] = true; sum[1] = lazy[1] = 0;
int mid = (l + r) >> 1,i = el - 1,t;
for (int k = el; k <= er; k++){
if (e[k].p == 1){
if (e[k].v > mid){
L = e[k].l; R = e[k].r;
update(1,1,n);
e[k].k = 1;
}else {
e[k].k = 0;
i++;
}
}
else {
L = e[k].l; R = e[k].r;
t = Query(1,1,n);
if (e[k].v <= t) e[k].k = 1;
else {
e[k].v -= t;
e[k].k = 0;
i++;
}
}
}
sort(e + el,e + er + 1,cmp);
solve(l,mid,el,i);
solve(mid + 1,r,i + 1,er);
}
} void init(){
n = read(); M = read();
REP(i,M){
e[i].p = read();
e[i].l = read();
e[i].r = read();
e[i].v = read();
if (e[i].p == 1) e[i].v = e[i].v + n;
e[i].id = i;
}
memset(ans,-1,sizeof(ans));
} void print(){
for (int i = 1; i <= M; i++)
if (ans[i] != -1) {
if (ans[i] == n) printf("50000\n");
else printf("%d\n",ans[i] - n);
}
} int main()
{
init();
solve(0,2 * n,1,M);
print();
return 0;
}
BZOJ3110 K大数查询 【线段树 + 整体二分 或 树套树(非正解)】的更多相关文章
- bzoj3110 [Zjoi2013]K大数查询——线段树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 外层权值线段树套内层区间线段树: 之所以外层权值内层区间,是因为区间线段树需要标记下传 ...
- bzoj 3110 [Zjoi2013]K大数查询——线段树套线段树(标记永久化)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 第一道线段树套线段树! 第一道标记永久化! 为什么为什么写了两个半小时啊…… 本想线段 ...
- 【BZOJ-3110】K大数查询 整体二分 + 线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6265 Solved: 2060[Submit][Sta ...
- BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)
3110 [Zjoi2013]K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a ...
- 【BZOJ3110】K大数查询(整体二分)
[BZOJ3110]K大数查询(整体二分) 题面 BZOJ 题解 看了很久整体二分 一直不知道哪里写错了 ... 又把树状数组当成线段树区间加法来用了.. 整体二分还是要想清楚在干什么: 我们考虑第\ ...
- BZOJ_3110_[Zjoi2013]K大数查询_整体二分+树状数组
BZOJ_3110_[Zjoi2013]K大数查询_整体二分+树状数组 Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位 ...
- BZOJ 3110 [Zjoi2013]K大数查询(整体二分)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 11654 Solved: 3505[Submit][St ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 418 Solved: 235 [ Submit][ ...
随机推荐
- C# webapi 路由规则和接收数据
1:新建的web api项目 默认的访问api方式: (get,post,delect,put) api+控制器 以Post为例子 post提交单个参数: 接收方法 post提交多个参数 接 ...
- 拼多多商品id怎么查看 拼多多店铺ID怎样看
网上开店平台有很多编号.id等可以区分商品和店铺的标志,拼多多有店铺id也有商品id,这是两个不同的概念,店铺id进入到拼多多店铺即可查询,拼多多商品id怎么查看 拼多多店铺ID怎样看,那么拼多多商品 ...
- Spring 定时任务Scheduled 开发详细图文
Spring 定时任务Scheduled 开发 文章目录 一.前言 1.1 定时任务 1.2 开发环境 1.3 技术实现 二.创建包含WEB.xml 的Maven 项目 2.1 创建多模块项目task ...
- 高可用Kubernetes集群-5. 部署flannel网络
七.部署flannel网络 kubernetes支持基于vxlan方式的flannel与weave网络,基于BGP路由的Calico网络,本节采用flannel网络. Flannel网络采用etcd等 ...
- Serverless 架构的优点和缺点
Serverless 的优势 在我使用 Serverless Framework 开发 AWS Serverless 应用的过程中,最方便的莫过于,第一次部署和第二次.第三次部署没有什么区别.只需要执 ...
- python中 try、except、finally 的执行顺序
def test1(): try: print('to do stuff') raise Exception('hehe') print('to return in try') return ...
- 软件工程课堂练习——找出1-n中1出现的个数
题目:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数. 要求:写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数.例如 f(12) = 5. 在3 ...
- 博弈---巴什博奕(Bash Game)(博弈入门)
巴什博奕(Bash Game):只有一堆n个物品,两个人轮流从这堆物品中取物,规 定每次至少取一个,最多取m个.最后取光者得胜. 显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走 ...
- 第八章 Mysql运算符
算术运算符 符号 表达式形式 作用 + x1+x2 加法 - x1-x2 减法 * x1*x2 乘法 / x1/x2 除法 div x1 div x2 同上 % x1%x2 取余 mod mod(x1 ...
- python接口自动化测试框架实现之操作oracle数据库
python操作oracle数据库需要使用到cx-oracle库. 安装:pip install cx-oracle python连接oracle数据库分以下步骤: 1.与oracle建立连接: 2. ...