• HEOI2016/TJOI2016 排序


    题目传送门

    奇妙的题目


    把操作离线下来,二分第(q)位置上的数(x),将排列中大于(x)的数记为(1),小于(x)的数记为(0),然后就可以很简单的用线段树维护每个操作
    最后判断(q)位置上的数是否为(1)
    时间复杂度(O(nlog^2 n))

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #define LL long long
    #define ls p << 1
    #define rs p << 1 | 1
    #define mid ((l+r) >> 1)
    using namespace std;
    LL read() {
        LL k = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9')
          k = k * 10 + c - 48, c = getchar();
        return k * f;
    }
    struct zzz {
    	int num1, num0;
    }tree[100010 << 2];
    struct hhh {
    	bool opt; int l, r;
    }que[100010];
    int tag[100010 << 2];
    int n, q, pos, a[100010], b[100010];
    inline void up(int p) {
    	tree[p].num0 = tree[ls].num0 + tree[rs].num0;
    	tree[p].num1 = tree[ls].num1 + tree[rs].num1;
    }
    inline void down(int p) {
    	if(tag[p] != -1) {
    		if(!tag[p]) {
    			tree[ls].num0 = tree[ls].num0 + tree[ls].num1;
    			tree[ls].num1 = 0;
    			tree[rs].num0 = tree[rs].num0 + tree[rs].num1;
    			tree[rs].num1 = 0;
    			tag[ls] = tag[rs] = tag[p]; tag[p] = -1;
    		}
    		else {
    			tree[ls].num1 = tree[ls].num0 + tree[ls].num1;
    			tree[ls].num0 = 0;
    			tree[rs].num1 = tree[rs].num0 + tree[rs].num1;
    			tree[rs].num0 = 0;
    			tag[ls] = tag[rs] = tag[p]; tag[p] = -1;
    		}
    	}
    }
    void build(int l = 1, int r = n, int p = 1) {
    	tag[p] = -1; tree[p].num0 = tree[p].num1 = 0;
    	if(l == r) {
    		if(a[l]) tree[p].num1 = 1;
    		else tree[p].num0 = 1;
    		return ;
    	}
    	build(l, mid, ls); build(mid+1, r, rs);
    	up(p);
    }
    int query(int nl, int nr, int l = 1, int r = n, int p = 1) {
    	if(nl <= l && nr >= r) return tree[p].num0;
    	down(p);
    	int ans = 0;
    	if(nl <= mid) ans += query(nl, nr, l, mid, ls);
    	if(nr > mid) ans += query(nl, nr, mid+1, r, rs);
    	return ans;
    }
    void update(int nl, int nr, bool k, int l = 1, int r = n, int p = 1) {
    	if(nl <= l && nr >= r) {
    		if(!k) {
    			tree[p].num0 = tree[p].num0 + tree[p].num1;
    			tree[p].num1 = 0; tag[p] = k;
    		}
    		else {
    			tree[p].num1 = tree[p].num0 + tree[p].num1;
    			tree[p].num0 = 0; tag[p] = k;
    		}
    		return ;
    	}
    	down(p);
    	if(nl <= mid) update(nl, nr, k, l, mid, ls);
    	if(nr > mid) update(nl, nr, k, mid+1, r, rs);
    	up(p);
    }
    
    bool check(int k) {
    	build();
    	for(int i = 1; i <= q; ++i) {
    		int cnt = query(que[i].l, que[i].r);
    		//注意区间全部为1和全部为0的情况
    		if(cnt == 0) {
    			update(que[i].l, que[i].r, 1); continue;
    		}
    		if(cnt == que[i].r-que[i].l+1) {
    			update(que[i].l, que[i].r, 0); continue;
    		}
    		if(que[i].opt)
    			update(que[i].l, que[i].r-cnt, 1),
    			update(que[i].r-cnt+1, que[i].r, 0);
    		else
    			update(que[i].l, que[i].l+cnt-1, 0),
    			update(que[i].l+cnt, que[i].r, 1);
    	}
    	return !query(pos, pos);
    }
    int main() {
    	n = read(), q = read();
    	for(int i = 1; i <= n; ++i) b[i] = read();
    	for(int i = 1; i <= q; ++i)
    		que[i].opt = read(), que[i].l = read(), que[i].r = read();
    	pos = read();
    	int l = 1, r = n, ans = 0;
    	while(l <= r) {
    		for(int i = 1; i <= n; ++i)
    			if(b[i] >= mid) a[i] = 1;
    			else a[i] = 0;
    		if(check(mid)) ans = mid, l = mid+1;
    		else r = mid - 1;
    	}
    	cout << ans;
        return 0;
    }
    
  • 相关阅读:
    ( 转 ) Mysql group_concat 的反向应用实现(Mysql列转行)
    ( 转 ) 优化 Group By -- MYSQL一次千万级连表查询优化
    ( 转 ) mysql复合索引、普通索引总结
    ( 转 ) 数据库BTree索引、Hash索引、Bitmap位图索引的优缺点
    ( 转 ) mysql 实战 or、in与union all 的查询效率
    ( 转 ) MySQL高级 之 explain执行计划详解
    ( 转 ) UML 类图
    ( 转 ) .net 操作 JWT
    windows 常用命令
    windows 执行bat脚本
  • 原文地址:https://www.cnblogs.com/morslin/p/11855715.html
Copyright © 2020-2023  润新知