码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5649 DZY Love Sorting 题解(二分套线段树)

时间:2021-04-14 12:37:08      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:blank   uil   love   两种   turn   sig   二分答案   c++   大小   

题目链接

题目大意

有一个数组 \(a\),它是一个长度为\(n(n\le1e5)\)的全排列。

现在他想执行多次下列两种操做:

  • \(0\;l\;r\)表示对\(a[l..r]\)进行升序排序
  • \(1\; l\; r\)表示对 \(a[l..r]\) 进行降序排序

问经过 \(m(m\le1e5)\)次操作后\(a[k]\)为多少?

题目思路

这个题目挺难的

直接模拟题意显然会\(TLE\)

因为我们最终只要求一个元素,考虑二分答案\(x\)

那么排列中大于等于\(x\)的数全都设为\(1\),小于\(x\)的数都设为 \(0\)

若为升序排序

现在区间排序,只要把区间里的\(0\)都移到最前面, \(1\)都移到最后面。

对于区间\([l, r]\)查询\([l, r]\)的子段和\(sum\)

然后将\([l, r - sum]\)修改为 \(0\)\([r - sum + 1, r]\)修改为\(1\).

反之亦然

这个题目主要是考虑相对大小

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n,m,k;
int a[maxn];
int tree[maxn<<2],lazy[maxn<<2];
int opt[maxn],l[maxn],r[maxn];
void build(int node,int l,int r,int x){
    lazy[node]=-1;
    if(l==r){
        tree[node]=(a[l]>=x);
        return ;
    }
    int mid=(l+r)/2;
    build(node<<1,l,mid,x);
    build(node<<1|1,mid+1,r,x);
    tree[node]=tree[node<<1]+tree[node<<1|1];
}

void updown(int node,int l,int r){
    if(lazy[node]!=-1){
        int mid=(l+r)/2;
        lazy[node<<1]=lazy[node];
        lazy[node<<1|1]=lazy[node];
        tree[node<<1]=(mid-l+1)*lazy[node];
        tree[node<<1|1]=(r-mid)*lazy[node];
        lazy[node]=-1;
    }
}
void update(int node,int L,int R,int l,int r,int add){
    if(L<=l&&r<=R){
        tree[node]=(r-l+1)*add;
        lazy[node]=add;
        return ;
    }
    updown(node,l,r);
    int mid=(l+r)/2;
    if(mid>=L) update(node<<1,L,R,l,mid,add);
    if(mid<R)  update(node<<1|1,L,R,mid+1,r,add);
    tree[node]=tree[node<<1]+tree[node<<1|1];
}
int query(int node,int L,int R,int l,int r){
    if(L<=l&&r<=R){
        return tree[node];
    }
    updown(node,l,r);
    int mid=(l+r)/2,sum=0;
    if(mid>=L) sum+=query(node<<1,L,R,l,mid);
    if(mid<R)  sum+=query(node<<1|1,L,R,mid+1,r);
    return sum;
}

bool check(int x){
    build(1,1,n,x);
    for(int i=1;i<=m;i++){
        int sum=query(1,l[i],r[i],1,n);
        if(opt[i]==0){
            if(r[i]-sum>=l[i])  update(1,l[i],r[i]-sum,1,n,0);
            if(r[i]>=r[i]-sum+1) update(1,r[i]-sum+1,r[i],1,n,1);
        }else{
            if(l[i]+sum-1>=l[i])  update(1,l[i],l[i]+sum-1,1,n,1);
            if(r[i]>=l[i]+sum) update(1,l[i]+sum,r[i],1,n,0);
        }
    }
    return query(1,k,k,1,n);
}
signed main(){
    int _;scanf("%d",&_);
    while(_--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&opt[i],&l[i],&r[i]);
        }
        scanf("%d",&k);
        int l=1,r=n,ans=-1;
        while(l<=r){
            if(check(mid)){
                ans=mid;
                l=mid+1;
            }else{
                r=mid-1;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


HDU 5649 DZY Love Sorting 题解(二分套线段树)

标签:blank   uil   love   两种   turn   sig   二分答案   c++   大小   

原文地址:https://www.cnblogs.com/hunxuewangzi/p/14656265.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!