K大数查询 HYSBZ - 3110

K大数查询

HYSBZ - 3110

本来是刷整体二分的,被这个sb题折腾了一下午,用cin就RE, 用scanf就过了=_=

收获就是偶然学到了树状数组区间修改区间查询的写法吧。。。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 #define LL long long
  6 const int maxn = 1e5 + 10;
  7 const int maxq = 5e4 + 10;
  8 struct Qry{
  9     int a, b;
 10     LL c;
 11     int id;
 12     Qry(int a = 0, int b = 0, LL c = 0, int id = 0):
 13         a(a), b(b), c(c), id(id){}
 14 }q[maxq], q1[maxq], q2[maxq];
 15
 16
 17 struct Seg{
 18     LL sum[maxn<<2], add[maxn<<2];
 19     void init(){
 20         memset(add, 0, sizeof add);
 21         memset(sum, 0, sizeof sum);
 22     }
 23     void pushup(int rt){
 24         sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 25     }
 26     void pushdown(int rt, int m){
 27         if(add[rt]){
 28             sum[rt<<1] += (m - (m>>1)) * add[rt];
 29             sum[rt<<1|1] += (m >> 1) * add[rt];
 30             add[rt<<1] += add[rt];
 31             add[rt<<1|1] += add[rt];
 32             add[rt] = 0;
 33         }
 34     }
 35
 36     void update(int L, int R, int v, int l, int r, int rt){
 37         if(L <= l && r <= R){
 38             sum[rt] += v * (r - l + 1);
 39             add[rt] += v;
 40             return;
 41         }
 42         pushdown(rt, r - l + 1);
 43         int m = (l + r) >> 1;
 44         if(L <= m) update(L, R, v, l, m, rt<<1);
 45         if(R > m) update(L, R, v, m + 1, r, rt<<1|1);
 46         pushup(rt);
 47     }
 48
 49     LL query(int L, int R, int l, int r, int rt){
 50         if(L <= l && r <= R){
 51             return sum[rt];
 52         }
 53         pushdown(rt, r - l + 1);
 54         int m = (l + r) >> 1;
 55         LL res = 0;
 56         if(L <= m) res += query(L, R, l, m, rt<<1);
 57         if(R > m) res += query(L, R, m + 1, r, rt<<1|1);
 58         return res;
 59     }
 60 }seg;
 61 int ans[maxq];
 62 int n;
 63 void solve(int L, int R, int l, int r){
 64     if(L > R) return;
 65     if(l == r){
 66         for(int i = L; i <= R; i++){
 67             if(q[i].id > 0) ans[q[i].id] = l;
 68         }
 69         return;
 70     }
 71     int m = (l + r) >> 1;
 72     int f = 0, g = 0;
 73     for(int i = L; i <= R; i++){
 74         if(q[i].id < 0){
 75             if(q[i].c <= m){
 76                 seg.update(q[i].a, q[i].b, 1, 1, n, 1);
 77                 q1[f++] = q[i];
 78             }else q2[g++] = q[i];
 79         }else{
 80             LL temp = seg.query(q[i].a, q[i].b, 1, n, 1);
 81             if(temp >= q[i].c) q1[f++] = q[i];
 82             else{
 83                 q[i].c -= temp;
 84                 q2[g++] = q[i];
 85             }
 86         }
 87     }
 88     for(int i = 0; i < f; i++) if(q1[i].id < 0) seg.update(q1[i].a, q1[i].b, -1, 1, n, 1);
 89     memcpy(q + L, q1, f * sizeof(Qry));
 90     memcpy(q + L + f, q2, g * sizeof(Qry));
 91     solve(L, L + f - 1, l, m);
 92     solve(L + f, R, m + 1, r);
 93 }
 94
 95 int main(){
 96     int m;
 97     while(scanf("%d %d", &n, &m) != EOF){
 98         int op, a, b;
 99         LL c;
100         seg.init();
101         int cnt = 0;
102         for(int i = 1; i <= m; i++){
103             cin>>op>>a>>b>>c;
104             if(op == 1){
105                 q[i] = Qry(a, b, n + 1LL - c, -1);
106             }else{
107                 q[i] = Qry(a, b, c, ++cnt);
108             }
109         }
110         solve(1, m, 1, n * 2LL + 1);
111         for(int i = 1; i <= cnt; i++) printf("%d\n", n - ans[i] + 1);
112     }
113 }

线段树维护

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 #define LL long long
 6 const int maxn = 1e5 + 10;
 7 const int maxq = 1e5 + 10;
 8 struct Qry{
 9     int a, b;
10     LL c;
11     int id;
12     Qry(int a = 0, int b = 0, LL c = 0, int id = 0):
13         a(a), b(b), c(c), id(id){}
14 }q[maxq], q1[maxq], q2[maxq];
15 //树状数组区间修改区间求和 http://blog.csdn.net/blackjack_/article/details/74997479
16 struct Bit{
17     int n;
18     LL c1[maxn], c2[maxn];
19     void init(int _n){
20         n = _n;
21         memset(c1, 0, sizeof(c1));
22         memset(c2, 0, sizeof(c2));
23     }
24     void add(int x,LL add){
25         for(int i=x;i<=n;i+=i&(-i)){
26             c1[i]+=add;
27             c2[i]+=x*add;
28         }
29     }
30     LL sum(int x){
31         LL ans=0;
32         for(int i=x;i>0;i-=i&(-i)){
33             ans+=(x+1)*c1[i]-c2[i];
34         }
35         return ans;
36     }
37 }bit;
38 int ans[maxq];
39 int n;
40 void solve(int L, int R, int l, int r){
41     if(L > R) return;
42     if(l == r){
43         for(int i = L; i <= R; i++){
44             if(q[i].id > 0) ans[q[i].id] = l;
45         }
46         return;
47     }
48     int m = (l + r) >> 1;
49     int f = 0, g = 0;
50     for(int i = L; i <= R; i++){
51         if(q[i].id < 0){
52             if(q[i].c <= m){
53                 bit.add(q[i].a, 1LL);
54                 bit.add(q[i].b+1, -1LL);
55                 q1[f++] = q[i];
56             }else q2[g++] = q[i];
57         }else{
58             LL temp = bit.sum(q[i].b) - bit.sum(q[i].a - 1);
59             if(temp >= q[i].c) q1[f++] = q[i];
60             else{
61                 q[i].c -= temp;
62                 q2[g++] = q[i];
63             }
64         }
65     }
66     for(int i = 0; i < f; i++) if(q1[i].id < 0 && q1[i].c <= m) {
67         bit.add(q1[i].a, -1);
68         bit.add(q1[i].b + 1, 1);
69     }
70     memcpy(q + L, q1, f * sizeof(Qry));
71     memcpy(q + L + f, q2, g * sizeof(Qry));
72     solve(L, L + f - 1, l, m);
73     solve(L + f, R, m + 1, r);
74 }
75
76 int main(){
77     int m;
78     while(scanf("%d %d", &n, &m)!= EOF){
79         int op, a, b;
80         LL c;
81         bit.init(n);
82         int cnt = 0;
83         for(int i = 1; i <= m; i++){
84             cin>>op>>a>>b>>c;
85             if(op == 1){
86                 q[i] = Qry(a, b, n + 1LL - c, -1);
87             }else{
88                 q[i] = Qry(a, b, c, ++cnt);
89             }
90         }
91         solve(1, m, 1, n * 2LL + 1);
92         for(int i = 1; i <= cnt; i++) printf("%d\n", n - ans[i] + 1);
93     }
94 }

树状数组维护

原文地址:https://www.cnblogs.com/yijiull/p/8324723.html

时间: 2024-10-06 05:03:42

K大数查询 HYSBZ - 3110的相关文章

K大数查询 bzoj 3110

K大数查询 [问题描述] 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. [输入格式] 第一行N,M 接下来M行,每行形如1 a b c或2 a b c [输出格式] 输出每个询问的结果 [样例输入] 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 [样例输出] 1 2 1 [样例说明] 第一个操作 后位置

【ZJOI2013】k大数查询 BZOJ 3110

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

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

BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ----------------------------------------------------------------------------------------- #include<cstdio> #include<cctype> #include<cstring> #include<algorithm> using namespace std;

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

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Status][Discuss] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a

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

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 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

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

[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 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 Outpu

【BZOJ-3110】K大数查询 整体二分 + 线段树

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Status][Discuss] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a

【BZOJ3110】[Zjoi2013]K大数查询 树套树

[BZOJ3110][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 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3

1501130926-蓝桥杯- 算法训练 区间k大数查询

算法训练 区间k大数查询 时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个包含一个正整数m,表示询问个数. 接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个.序列元素从1开始标号. 输出格式 总共输出m行,每行一个数,表示询问的答案. 样例输入 5 1 2 3 4 5 2 1