zoukankan      html  css  js  c++  java
  • 【HEOI/TJOI2016】排序

    一道神题ORZ,思路真的很妙啊。

    正文部分:

    题意:

    给一个序列,可以对某一个区间升序和降序排序,问你最后数列中第(Q)个数是什么?
    乍一看貌似毫无思路,于是我们考虑一个更简单的问题:
    如果对(1)(01)序列执行上面的操作,是不是就可以变得简单一点?
    设某段区间([l,r])里总共有(cnt)个1
    那么降序排就是把(lsim l+cnt - 1)修改为(1),把(l+cnt sim r)修改为(0)
    升序排则是把(r-cnt+1sim r)修改为(1),(lsim r-cnt)修改为(0)
    其实一个(01)序列有多少个(1)就是这个序列的和。
    于是这样就变成了一道线段树问题:
    区间修改,区间求和

    于是我们回归原题,看是否能用一种“(01)序列”的方法维护原数列。
    答案是可以的。
    对于某一个数,我们把大于它的数设为(1),小于它的数设为(0),于是我们就得到了一个(01)序列。
    把所有操作全部离线,跑一遍,于是我们就可以二分了。
    为什么可以二分?
    我们设想一下,如果这个(01)序列最后第(Q)位是(1),说明最后的答案一定比这个数大,否则则一定比这个数小。

    而题目又保证了一定为全排列,所以答案肯定只有一个。
    于是这道题就变成了一个二分+线段树问题,可以通过了。

    #include <bits/stdc++.h>
    #define gc getchar
    #define il inline
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)
    const int MAXN = 1e5 + 10;
    const int MAXQ = MAXN;
    using namespace std;
    int n,m,i,j,k,ans,Q;
    int a[MAXN];bool b[MAXN];
    int tr[MAXN << 2],tag[MAXN << 2];
    struct Questions {
    	int l,r;bool opt;
    	Questions() {l = r = opt = 0;}
    	Questions(int L,int R,int Opt) {
    		l = L;r = R;opt = Opt;
    	}
    }query[MAXQ];
    il int read() {
    	int res = 0;char c;bool sign = 0;
    	for(c = gc();!isdigit(c);c = gc()) sign |= c == '-';
    	for(;isdigit(c);c = gc()) res = (res << 1) + (res << 3) + (c ^ 48);
    	return sign ? -res : res;
    }
    il void pushup(int num) {
    	tr[num] = tr[lson(num)] + tr[rson(num)];
    	return;
    }
    il void init(int num,int l,int r,int val) {
    	tr[num] = (r - l + 1) * val;
    	tag[num] = val; 
    	return;
    }
    il void pushdown(int num,int l,int r) {
    	if(~tag[num]) {
    		int mid = l + r >> 1;
    		init(lson(num),l,mid,tag[num]);
    		init(rson(num),mid + 1,r,tag[num]);
    		tag[num] = -1;
    	}
    	return;
    }
    void build(int l,int r,int num) {
    	if(l == r) {tr[num] = b[l];return;}
    	int mid = l + r >> 1;
    	build(l,mid,lson(num));
    	build(mid + 1,r,rson(num));
    	pushup(num);
    	return;
    }
    void modify(int ml,int mr,int l,int r,int num,int val) {
       if(ml <= l && r <= mr) {
            tr[num] = (r - l + 1) * val;
            tag[num] = val;
            return;
        }
        int mid = l + r >> 1;
        pushdown(num,l,r);
        if(ml <= mid) modify(ml,mr,l,mid,lson(num),val);
        if(mid < mr)  modify(ml,mr,mid + 1,r,rson(num),val);
        pushup(num);return; 
    }
    int Query(int ql,int qr,int l,int r,int num) {
    	if(ql <= l && r <= qr) return tr[num];
    	pushdown(num,l,r);
    	int mid = l + r >> 1,res = 0;
    	if(ql <= mid) res += Query(ql,qr,l,mid,lson(num));
    	if(mid < qr)  res += Query(ql,qr,mid + 1,r,rson(num));
    	return res;
    }
    il bool judge(int cknum) {
    	for(int i = 1;i <= n;i++) {
    		b[i] = a[i] >= cknum;
    	} 
    	memset(tr,0,sizeof(tr));
    	memset(tag,-1,sizeof(tag));
    	build(1,n,1);
    	for(int i = 1;i <= m;i++) {
    		int opt = query[i].opt;
    		int l = query[i].l;
    		int r = query[i].r;
    		int cnt = Query(l,r,1,n,1);
    		if(!opt) {
    			modify(r - cnt + 1,r,1,n,1,1);
    			modify(l,r - cnt,1,n,1,0);
    		} else {
    			modify(l,l + cnt - 1,1,n,1,1);
    			modify(l + cnt,r,1,n,1,0);
    		}
    	}
    	return Query(Q,Q,1,n,1);
    }
    int main() {
    	n = read();m = read();
    	for(int i = 1;i <= n;i++) a[i] = read();
    	for(int i = 1;i <= m;i++) {
    		query[i].opt = read();
    		query[i].l = read();
    		query[i].r = read();
    	}		
    	Q = read();
    	int l = 1,r = n;
    	while(l <= r) {
    		int mid = l + r >> 1;
    		if(judge(mid)) l = mid + 1,ans = mid;
    		else r = mid - 1;
    	}	
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    Atitit 集团与个人的完整入口列表 attilax的完整入口 1. 集团与个人的完整入口列表 1 2. 流量入口概念 2 3. 流量入口的历史与发展 2 1.集团与个人的完整入口列表
    atitit 每季度日程表 每季度流程 v3 qaf.docx Ver history V2 add diary cyar data 3 cate V3 fix detail 3cate ,
    Atitit react 详细使用总结 绑定列表显示 attilax总结 1. 前言 1 1.1. 资料数量在百度内的数量对比 1 1.2. 版本16 v15.6.1 1 1.3. 引入js 2
    Atitit r2017 r3 doc list on home ntpc.docx
    Atitit r2017 ra doc list on home ntpc.docx
    Atiitt attilax掌握的前后技术放在简历里面.docx
    Atitit q2016 qa doc list on home ntpc.docx
    Atitit r7 doc list on home ntpc.docx 驱动器 D 中的卷是 p2soft 卷的序列号是 9AD0D3C8 D:\ati\r2017 v3 r01\
    Atitit 可移植性之道attilax著
    Atitit q2016 q5 doc list on home ntpc.docx
  • 原文地址:https://www.cnblogs.com/Sai0511/p/10360141.html
Copyright © 2011-2022 走看看