zoukankan      html  css  js  c++  java
  • bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 线段树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552

    题意:

    给你一个1-n的全排列,m次操作,操作由两种:1.将[l,r]升序排序,2.将[l,r]降序排列

    最后给你一个点p,输出这个点的数

    思路:

    因为这道题只有一个询问,只需要知道一个位置的值,且序列是全排列,那么我们可以对答案进行二分,首先我们先选定一个值x,将数组中比x大的全部变成1,小于等于x的变为0,然后用线段树去模拟排序的操作,最后我们需要查询p位置的数如果为1那么代表答案大于当前数x,为0代表答案小于当前数x,继续二分就好了

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    const int M = 1e5 +10;
    int sum[M<<2],flag[M<<2],lazy[M<<2],a[M],b[M],op[M];
    struct node{
        int l,r;
    }q[M];
    
    void pushup(int rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void pushdown(int l,int r,int rt){
        if(flag[rt]){
            mid;
            sum[rt<<1] = lazy[rt]*(m-l+1);
            sum[rt<<1|1] = lazy[rt]*(r-m);
            lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
            flag[rt<<1] = flag[rt<<1|1] = flag[rt];
            flag[rt] = 0;
        }
    }
    
    void build(int l,int r,int rt){
        flag[rt] = 0; lazy[rt] = 0;
        if(l == r){
            sum[rt] = b[l];
            return;
        }
        mid;
        build(lson); build(rson);
        pushup(rt);
    }
    
    void update(int L,int R,int c,int l,int r,int rt){
        if(L <= l&&R >= r){
            sum[rt] = c*(r-l+1);
            lazy[rt] = c; flag[rt] = 1;
            return ;
        }
        pushdown(l,r,rt);
        mid;
        if(L <= m) update(L,R,c,lson);
        if(R > m) update(L,R,c,rson);
        pushup(rt);
    }
    
    int query(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        pushdown(l,r,rt);
        mid;
        int ret = 0;
        if(L <= m) ret += query(L,R,lson);
        if(R > m) ret += query(L,R,rson);
        return ret ;
    }
    
    int main()
    {
        int n,k,pos;
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;i ++)
            scanf("%d",&a[i]);
        for(int i = 1;i <= k;i ++)
            scanf("%d%d%d",&op[i],&q[i].l,&q[i].r);
        scanf("%d",&pos);
        int l = 1,r = n;
        while(l < r){
            mid;
            for(int i = 1;i <= n;i ++){
                if(a[i] > m) b[i] = 1;
                else b[i] = 0;
            }
            build(1,n,1);
            for(int i = 1;i <= k;i ++){
                int cnt = query(q[i].l,q[i].r,1,n,1);
                if(op[i]){  //降序排列,1放在前面,0放在后面
                    if(cnt) update(q[i].l,q[i].l+cnt-1,1,1,n,1);
                    if(cnt+q[i].l <= q[i].r) update(q[i].l+cnt,q[i].r,0,1,n,1);
                }
                else{  //升序排序,1放在后面,0放在前面
                    if(cnt) update(q[i].r-cnt+1,q[i].r,1,1,n,1);
                    if(q[i].r-cnt >= q[i].l) update(q[i].l,q[i].r-cnt,0,1,n,1);
                }
            }
            if(query(pos,pos,1,n,1)) l = m+1;
            else r = m;
        }
        printf("%d
    ",l);
        return 0;
    }
  • 相关阅读:
    微软官方Silverlight5新特性完整介绍
    Windows Phone 7外包(承接WP7项目外包 可签合同 长期有效)
    我们为什么要选择Silverlight?(CSDN网友的见解分享大家)【转】
    开博记录02120928
    [转载]在linux下如何制作img的映像文件
    JavaScript中的null和undefined
    年度映像
    25岁毕业,拿一万块钱月薪
    saymedia bug问题
    mxp组件开发及jsfl文件
  • 原文地址:https://www.cnblogs.com/kls123/p/9574639.html
Copyright © 2011-2022 走看看