zoukankan      html  css  js  c++  java
  • LG P2839 [国家集训队]middle

    \(\text{Solution}\)

    不考虑起点区间和终点区间的限制,求区间中位数
    可以二分中位数,大于等于中位数的位置赋为 \(1\),小于的位置赋 \(-1\)
    当区间和大于等于 \(0\) 时此数才可能为中位数
    因为有多个询问,但中位数数值只可能有 \(n\)
    所以预处理时枚举当前中位数,处理出序列此时区间和的情况,线段树即可
    但一棵线段树空间是 \(O(n log n)\) 的,\(n\) 棵不可行
    注意到中位数 \(m\)\(m+1\) 时只有值为 \(m\) 的位置从 \(1\) 变到了 \(-1\),其他都一样
    启示我们可以用主席树维护,于是这个问题就解决了

    回到本题,仍旧预处理并且二分答案
    起点区间和终点区间夹的区间是必选的,取出区间和即可
    起点和终点待定,确定某个起点后,此起点到起点区间右端点的数都要选,终点同理,即取后缀和前缀
    那么在二分中位数的情况下,前缀和后缀越大越好
    维护区间和时顺便维护区间最大前后缀即可

    \(\text{Code}\)

    #include <cstdio>
    #include <algorithm>
    #define re register
    using namespace std;
    
    const int N = 20005, INF = N * 10;
    int n, m, q[4], rt[N], size;
    struct nod{int v, id;}a[N];
    inline bool cmp(nod a, nod b){return a.v < b.v;}
    
    struct node{int sum, lx, rx;};
    struct tree{int ls, rs; node t;}seg[N * 61];
    inline node operator + (const node &a, const node &b)
    {
    	return node{a.sum + b.sum, max(a.lx, a.sum + b.lx), max(b.rx, b.sum + a.rx)};
    }
    
    void update(int &p, int pre, int l, int r, int x, int v)
    {
    	p = ++size, seg[p] = seg[pre];
    	if (l == r)
    	{
    		seg[p].t.sum += v, seg[p].t.lx += v, seg[p].t.rx += v;
    		return;
    	}
    	int mid = l + r >> 1;
    	if (x <= mid) update(seg[p].ls, seg[pre].ls, l, mid, x, v);
    	else update(seg[p].rs, seg[pre].rs, mid + 1, r, x, v);
    	seg[p].t = seg[seg[p].ls].t + seg[seg[p].rs].t;
    }
    
    node query(int p, int l, int r, int tl, int tr)
    {
    	if (tl > r || tr < l) return node{0, -INF, -INF};
    	if (tl <= l && r <= tr) return seg[p].t;
    	int mid = l + r >> 1; node res = {0, -INF, -INF};
    	if (tl <= mid) res = query(seg[p].ls, l, mid, tl, tr);
    	if (tr > mid) res = res + query(seg[p].rs, mid + 1, r, tl, tr);
    	return res;
    }
    
    inline int check(int mid)
    {
    	int res = 0;
    	if (q[1] + 2 <= q[2]) res = query(rt[mid], 1, n, q[1] + 1, q[2] - 1).sum;
    	res += query(rt[mid], 1, n, q[0], q[1]).rx + query(rt[mid], 1, n, q[2], q[3]).lx;
    	return res >= 0;
    }
    
    int main()
    {
    	freopen("LG2839.in", "r", stdin), freopen("LG2839.out", "w", stdout);
    	scanf("%d", &n);
    	for(re int i = 1; i <= n; i++) scanf("%d", &a[i].v), a[i].id = i;
    	sort(a + 1, a + n + 1, cmp);
    	for(re int i = 1; i <= n; i++) update(rt[1], rt[1], 1, n, i, 1);
    	for(re int i = 2; i <= n; i++) update(rt[i], rt[i - 1], 1, n, a[i - 1].id, -2);
    	
    	scanf("%d", &m);
    	for(int l, r, mid, ans, lst = 0; m; --m)
    	{
    		for(int i = 0; i < 4; i++) scanf("%d", &q[i]), q[i] = (q[i] + lst) % n + 1;
    		sort(q, q + 4), l = 1, r = n, ans = 0;
    		while (l <= r)
    		{
    			mid = l + r >> 1;
    			if (check(mid)) ans = mid, l = mid + 1;
    			else r = mid - 1;
    		}
    		printf("%d\n", lst = a[ans].v);
    	}
    }
    
  • 相关阅读:
    【推荐】微服务分布式企业框架Springmvc+mybatis+shiro+Dubbo+ZooKeeper+Redis
    将WCF寄宿在托管的Windows服务中
    剑指Offer
    剑指Offer
    Entity Framework 无法对没有主键的视图映射实体的解决办法
    设置Sql Agent运行Job时的执行账户
    IE中Keep-Alive机制引起的错误
    Ajax错误 “SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成” 的归纳总结
    在IIS站点中Adomd.net集成认证账号问题
    出现“不能执行已释放的Script代码”错误的原因及解决办法
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15548332.html
Copyright © 2011-2022 走看看