首页 > 其他分享 >P2839 [国家集训队] middle

P2839 [国家集训队] middle

时间:2024-04-24 13:24:39浏览次数:22  
标签:P2839 int data sum d2 middle d1 国家集训队 rk

Sol:

首先注意到答案是具有单调性的,考虑二分答案 \(x\) 解决。

令 $up(l, r, x)/down(l,r,x) $ 是 \([l,r]\) 中 大于等于/小于 \(x\) 的数。

那么对于一个区间 \([l,r]\),显然中位数 \(\ge x\) 的条件为 \(up(l, r, x) \ge down(l, r, x)\).

变形得到 \(up(l, r, x) - down(l ,r, x) \ge 0\)。于是非常自然的,我们令大于等于 \(x\) 的数为 \(1\), 小于等于 \(x\) 的数为 \(-1\)。

将区间拆分为 \([l, b], [b+1, c-1], [c,r]\),求出 \([a,b]\) 中的最大后缀和以及 \([c,r]\) 中的最大前缀和并判断三者加起来是否 \(>0\) 即可.

此时我们可以做到 \((n \log n)\) 回答一次询问。

如何优化呢?

注意到中位数的取值不大于 \(n\) 种可能,我们可以预处理出所有中位数时的序列形态。

先简化一下问题,只考虑一种中位数的时候如何维护查询。显然直接上线段数维护即可。

于是便自然的想到了可持久化线段树了,具体怎么做建议自己想想。

#include<bits/stdc++.h>
#define int long long 
#define zsw(x) ((x + lst) % n + 1)
using namespace std;

const int N = 1e5 + 10, INF = 0x3f3f3f3f;

int n, a[N], rk[N];
struct data{
	int pre, suf, sum;
};

data merge(struct data d1, struct data d2){
	data res;
	res.sum = d1.sum + d2.sum;
	res.pre = max(d1.pre, d1.sum + d2.pre);
	res.suf = max(d2.suf, d2.sum + d1.suf);
	return res;
}

namespace Persist_tree{
	#define mid (l + r >> 1)
	struct node{
		int ls, rs;
		data dat;
	}hjt[N << 5];
	int root[N], cnt;
	void pushup(int o){hjt[o].dat = merge(hjt[hjt[o].ls].dat, hjt[hjt[o].rs].dat);}
	void build(int& o, int l, int r){
		hjt[++cnt].dat = {-1, -1, -1}; o = cnt;
		if(l == r) return;
		build(hjt[o].ls, l, mid); build(hjt[o].rs, mid + 1, r);
		pushup(o); 
	}
	void add(int pre, int& o, int l, int r, int x){
		hjt[++cnt] = hjt[pre]; o = cnt;
		if(l == r){hjt[o].dat = (data){1, 1, 1}; return;}
		if(x <= mid) add(hjt[pre].ls, hjt[o].ls, l, mid, x);
		else add(hjt[pre].rs, hjt[o].rs, mid + 1, r, x);
		 pushup(o); //cout << l << " " << r << " " << hjt[o].dat.pre << " " << hjt[o].dat.suf << " " << hjt[o].dat.sum << "\n";
	}
	data querydat(int o, int l, int r, int s, int t){
        if(s > t) return {0, 0, 0};
		if(s <= l && r <= t) return hjt[o].dat;
        bool bls = (s <= mid), brs = (mid < t);
        if(bls && brs) return merge(querydat(hjt[o].ls, l, mid, s, t), querydat(hjt[o].rs, mid + 1, r, s, t));
        else if(bls) return querydat(hjt[o].ls, l, mid, s, t);
        else if(brs) return querydat(hjt[o].rs, mid + 1, r, s, t);
        else assert(0);
	}
}
using namespace Persist_tree;
vector<int>pos[N];

signed main(){
	ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i], rk[i] = a[i];
	sort(rk + 1, rk + n + 1); int Rksiz = unique(rk + 1, rk + n + 1) - (rk + 1); 
	for(int i = 1; i <= n; i++) a[i] = lower_bound(rk + 1, rk + Rksiz + 1, a[i]) - rk, pos[a[i]].push_back(i);
	build(root[Rksiz + 1], 1, n);
	for(int i = Rksiz; i > 0; i--){
        root[i] = root[i + 1];
		for(int j = 0; j < pos[i].size(); j++) add(root[i], root[i], 1, n, pos[i][j]);
	}
	int T, lst = 0; cin >> T;
	int q[5];
	while(T--){
		int a, b, c, d;
		for(int i = 0; i < 4; i++) cin >> q[i], q[i] = zsw(q[i]);
		sort(q, q + 4); a = q[0], b = q[1], c = q[2], d = q[3]; //cout << a << " " << b << " " << c << " " << d << "\n";
		int l = 1, r = Rksiz, ans = 0;
		while(l <= r){
			int rank = querydat(root[mid], 1, n, b + 1, c - 1).sum + querydat(root[mid], 1, n, a, b).suf + querydat(root[mid], 1, n, c, d).pre;
			// cout << mid << " " << rank << "\n"; 
            if(rank >= 0){
				ans = mid;
				l = mid + 1;
			}
			else r = mid - 1;
		}
		cout << (lst = rk[ans]) << "\n";
	}
	
	return 0;
}

标签:P2839,int,data,sum,d2,middle,d1,国家集训队,rk
From: https://www.cnblogs.com/little-corn/p/18155063

相关文章

  • 洛谷 P4451 [国家集训队] 整数的lqp拆分
    洛谷传送门设\(G\)为斐波那契数列的生成函数,显然有\(F=F\timesG+1\)。那么\(F=\frac{1}{1-G}=1+\frac{x}{1-2x-x^2}\)。问题是如何展开\(\frac{x}{1-2x-x^2}\)。因为\(\frac{1}{1-ax}=\sum\limits_{i\ge0}(ax)^i\),所以考虑设\(\frac{x}{1-......
  • 自定义 AuthorizationMiddleware 的行为
    在其它角色、策略权限验证后,系统再执行中间件,中间件成功后,最后才执行调用控制器方法。其它策略-》授权中间件-》控制器方法应用可以注册 IAuthorizationMiddlewareResultHandler,以自定义 AuthorizationMiddleware 处理授权结果的方式。应用可将 IAuthorizationMiddlewareRe......
  • C113 带修莫队 P1903 [国家集训队] 数颜色/维护队列
    视频链接:   LuoguP1903[国家集训队]数颜色/维护队列//带修莫队O(n^(5/3))#include<iostream>#include<cstring>#include<algorithm>#include<cmath>usingnamespacestd;constintN=1000005;intn,m,B,mq,mr,a[N];intsum,cnt[N],ans[N];st......
  • C112 莫队算法 P1494 [国家集训队] 小 Z 的袜子
    视频链接:  LuoguP1494[国家集训队]小Z的袜子//普通莫队O(n*sqrt(n))#include<iostream>#include<cstring>#include<algorithm>#include<cmath>usingnamespacestd;constintN=50005;intn,m,B,a[N];intsum,cnt[N],ans1[N],ans2[N];str......
  • LLM如何处理长上下文:Lost in the middle
    论文地址:LostintheMiddle:HowLanguageModelsUseLongContexts论文总结:写prompt的时候,需要注意内容的顺序,把重要的信息放在最前面或者最后面。大型语言模型大有用处,在设计prompt方面,人们通常建议为语言模型提供详尽的任务描述和背景信息。近期的一些语言模型有能力......
  • 中间件Middleware
    参考:https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.01、什么是中间件中间件是一种装配到应用管道以处理请求(Request)和响应(Response)的组件。每个组件:选择是否将请求传递到管道中的下一个组件。可在管道中的下一个组件前后执行......
  • P1975 [国家集训队] 排队 题解
    题目链接:排队水紫,\(n\)不大,树套树或者分块都能做。分块的话,最优序列分块套套值域分块最优。观察到是可差性问题维护,即权值数量维护,那我们就树状数组套权值线段树即可。由于\(n\)不大,我们可以不用回收标记,直接数组空间开大点就行。我们预处理出初始逆序对,每一次操作都是基于......
  • 控制ERP物料主数据通过Middleware传往CRM
    先说一下优化过滤的必要性。CRM物料主数据一百多万。感谢MDM或者相关的系统,每天通过接口更新的不知道什么东西,每天数百万的物料更新队列进入CRM。CRM系统被搞死了好几次。然后各种优化报表,程序。。。最后有几个链接缓慢的自开发接口,背锅了。。。好吧,先不管那些了。现在在ERP......
  • P4555 [国家集训队] 最长双回文串
    题目链接:https://www.luogu.com.cn/problem/P4555题解:要找一个由两个回文组成字符串,一定有一个分割的位置,将两个回文串分开,设分割x,x+1,可能成为最后答案的值一定是左边的最长回文串和右边的最长的回文串长度之和。   回文中心一个<x,一个>x+1且一定包含x和x+1。如果最......
  • P2757 [国家集训队] 等差子序列
    题目的等差子序列最少只要求长度为3,那么其实就转化为对于一个数是否存在左右各一个与它差值相等的一对数,比如14325中1,5对3来说就如此。这样的关系放到数轴上就是是否存在一对数到某数的距离相等。由于题目明确是一个排列,也就是1到n所有数一定会出现一次,那么对于某数,它左边的......