bzoj 4552

二分 + 线段树
二分一个值 x, 讲原序列转化为01序列
1表示该数>x, 0表示改数<x;
线段树维护区间和进行判断

#include <bits/stdc++.h>

const int N = 1e5 + 10;

#define gc getchar()

int n, m, Q;
int A[N], B[N];
int S[N << 2], W[N << 2], F[N << 2];
int opt[N], lask[N], rask[N];
int js;

inline int read() {
    int x = 0; char c = gc;
    while(c < ‘0‘ || c > ‘9‘) c = gc;
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = gc;
    return x;
}

#define lson jd << 1
#define rson jd << 1 | 1

void Build_size(int l, int r, int jd) {
    S[jd] = r - l + 1;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    Build_size(l, mid, lson);
    Build_size(mid + 1, r, rson);
} 

void Build_tree(int l, int r, int jd) {
    F[jd] = -1;
    if(l == r) {W[jd] = B[l]; return ;}
    int mid = (l + r) >> 1;
    Build_tree(l, mid, lson);
    Build_tree(mid + 1, r, rson);
    W[jd] = W[lson] + W[rson];
}

void Down(int jd) {
    F[lson] = F[rson] = F[jd];
    W[lson] = S[lson] * F[jd], W[rson] = S[rson] * F[jd];
    F[jd] = -1;
}

int Answer;

void Sec_A(int l, int r, int jd, int x, int y) {
    if(x > y) return ;
    if(x <= l && r <= y) {Answer += W[jd]; return ;}
    if(F[jd] != -1) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_A(l, mid, lson, x, y);
    if(y > mid)  Sec_A(mid + 1, r, rson, x, y);
}

void Sec_G(int l, int r, int jd, int x, int y, int how) {
    if(x > y) return ;
    if(x <= l && r <= y) {
        F[jd] = how;
        W[jd] = S[jd] * how;
        return ;
    }
    if(F[jd] != -1) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_G(l, mid, lson, x, y, how);
    if(y > mid)  Sec_G(mid + 1, r, rson, x, y, how);
    W[jd] = W[lson] + W[rson];
}

inline bool See(int x) {
    for(int i = 1; i <= n; i ++) B[i] = (A[i] >= x);
    Build_tree(1, n, 1);
    for(int i = 1; i <= m; i ++) {
        Answer = 0;
        Sec_A(1, n, 1, lask[i], rask[i]);
        int sum = Answer;
        if(!opt[i]) {
            Sec_G(1, n, 1, rask[i] - sum + 1, rask[i], 1);
            Sec_G(1, n, 1, lask[i], rask[i] - sum, 0);
        } else {
            Sec_G(1, n, 1, lask[i], lask[i] + sum - 1, 1);
            Sec_G(1, n, 1, lask[i] + sum, rask[i], 0);
        }
    }
    Answer = 0;
    Sec_A(1, n, 1, Q, Q);
    return Answer;
}

int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; i ++) A[i] = read();
    for(int i = 1; i <= m; i ++) opt[i] = read(), lask[i] = read(), rask[i] = read();
    Q = read();
    Build_size(1, n, 1);
    int L = 1, R = n, Ans(0);
    while(L <= R) {
        int Mid = (L + R) >> 1;
        if(See(Mid)) L = Mid + 1, Ans = Mid;
        else R = Mid - 1;
    }
    std:: cout << Ans;
    return 0;
}

原文地址:https://www.cnblogs.com/zjoiak/p/9125591.html

时间: 2024-11-01 22:10:12

bzoj 4552的相关文章

[BZOJ] 4552: [Tjoi2016&amp;Heoi2016]排序 #二分+线段树+算法设计策略

4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1451  Solved: 734[Submit][Status][Discuss] Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排 序分为两种:1:(0,l,r

bzoj 4552 [Tjoi2016&amp;Heoi2016]排序——二分答案

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成区间赋值了. #include<cstdio> #include<cstring> #include<algorithm> #define ls Ls[cr] #define rs Rs[cr] using namespace std; const int N=1e5+5,

排序(bzoj 4552)

Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排 序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q 位置上的数字. Input 输入数据的第一行为两个整数n和m.n表示序列的长度,m表示局部排序的次数.1 <= n, m <= 10^

bzoj 4552: [Tjoi2016&amp;Heoi2016]排序

Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排 序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q 位置上的数字. Input 输入数据的第一行为两个整数n和m.n表示序列的长度,m表示局部排序的次数.1 <= n, m <= 10^

BZOJ 4552 排序

省选TM都能有BC原题? ... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100500 #define inf 1000000007 using namespace std; int n,m,a[maxn],l=inf,r=0,mi,q; int ls[maxn<<2],rs[maxn<<2],lazy

【刷题记录】杂题记录

1.[bzoj 4552][Tjoi2016&Heoi2016]排序 题意:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序.排序分为两种:(0,l,r)表示将区间[l,r]的数字升序排序:(1,l,r)表示将区间[l,r]的数字降序排序.最后询问第q位置上的数字. 分析:二分答案,将所有值小于等于当前值的数赋为0,其余赋为1.利用线段树可以通过统计区间内数字1的个数来使当前区间有序.进行m次局部排序后可以得到答案与当前值的大小关系,满足可二分性. 1 #include<cstd

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比