P17143 [NOI 2026] 中位数 题解

题目链接:P17143 [NOI 2026] 中位数#18986. 中位数

简单题。二分答案,暴力 dp 的时间复杂度是 $ O(n^2klogn) $ 的,据说线段树优化可以做到 $ O(nklog^2n) $,但是我写假了。考虑找到任意 $ \lceil \frac{k}{2}\rceil $ 个中位数大于等于当前要求的中位数的段,显然这个最多会把整个序列分成 $ 2\lceil \frac{k}{2}\rceil + 1 $ 段,于是对于偶数 $ k $ 我们需要消掉一段,奇数 $ k $ 需要消掉两段。只要有一段中位数合法的段时序列的前缀或者后缀,或者两段合法的段是相邻的,就可以少掉一段,于是做简单分讨即可,然后发现这样对于 $ k=2, 3, 5 $ 时错了,那么拼上一个刚刚的线段树优化 dp 即可,但是我不会,所以我写了分讨。

代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#include"median.h"
using namespace std;
void init(int c,int t)
{
	return ;
}
vector<int> p,s;
int dp[1000005][6];
int tree[8000009];
void build(int l,int r,int id)
{
	tree[id]=0;
	if(l==r)
	{
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,id<<1);
	build(mid+1,r,id<<1|1);
	return ;
}
int query(int l,int r,int id,int qr)
{
	
	if(r<=qr)return tree[id];
	int mid=l+r>>1,ret=0;
	ret|=query(l,mid,id<<1,qr);
	if(mid<qr)ret|=query(mid+1,r,id<<1|1,qr);
//	cout<<l<<' '<<r<<' '<<ret<<'\n';
	return ret;
}
void update(int l,int r,int id,int x)
{
	if(l==r)
	{
		tree[id]=1;
		return ;
	}
	int mid=l+r>>1;
	if(x<=mid)update(l,mid,id<<1,x);
	else update(mid+1,r,id<<1|1,x);
	tree[id]=(tree[id<<1]|tree[id<<1|1]);
	return ;
}
void print(int l,int r,int id)
{
//	cout<<l<<' '<<r<<' '<<tree[id]<<'\n';
	if(l==r)
	{
		return ;
	}
	int mid=l+r>>1;
	print(l,mid,id<<1);
	print(mid+1,r,id<<1|1);
	return ;
}
bool check(int x,int K)
{
	int cnt=0,n=p.size();
//	if(K==89)cout<<x<<'\n';
	for(int i=0;i<n;i++)
	{
		cnt+=p[i];
//		if(K==89)cout<<p[i]<<' ';
	}
//	if(K==89)puts("");
	if(cnt<(K+1)/2)return 0;
	if(K>5||K==4)
	{
		int cnt2=0,pos1=-1,pos2=-1;
		cnt=0;
		for(int i=0;i<n;i++)
		{
			cnt+=p[i];
			if(cnt>=(i+2)/2)
			{
				pos1=i;
				break;
			}
		}
		cnt=0;
		for(int i=n-1;i>=0;i--)
		{
			cnt+=p[i];
			if(cnt>=(n-i+1)/2)
			{
				pos2=i;
				break;
			}
		}
		if(K%2==0)
		{
			if(pos1!=-1)
			{
				cnt=0;
				for(int i=pos1+1;i<n;i++)
				{
					cnt+=p[i];
				}
				if(cnt>=(K-1)/2)return 1;
			}
			if(pos2!=-1)
			{
				cnt=0;
				for(int i=0;i<pos2;i++)
				{
					cnt+=p[i];
				}
				if(cnt>=(K-1)/2)return 1;
			}
			for(int i=1;i<n;i++)
			{
				if(p[i]==1&&p[i-1]==1)return 1;
			}
			for(int i=2;i<n;i++)
			{
				if(p[i]==1&&p[i-2]==1)return 1;
			}
			for(int i=3;i<n;i++)
			{
				if(p[i]==1&&p[i-3]==1)return 1;
			}
			return 0;
		}
		else
		{
//			if(x==4229)
//			{
//				cout<<pos1<<' '<<pos2<<' '<<n<<'\n';
//				for(int i=0;i<n;i++)
//				{
//					cout<<p[i]<<' ';
//				}
//				puts("");
//			}
			if(pos1!=-1)
			{
				cnt=0;
				for(int i=pos1+1;i<n;i++)
				{
					cnt+=p[i];
				}
				if(cnt>=(K-1)/2)
				{
					for(int i=pos1+2;i<n;i++)
					{
						if(p[i]==1&&p[i-1]==1)return 1;
					}
					for(int i=pos1+3;i<n;i++)
					{
						if(p[i]==1&&p[i-2]==1)return 1;
					}
					for(int i=pos1+4;i<n;i++)
					{
						if(p[i]==1&&p[i-3]==1)return 1;
					}
					if((pos1+1<n&&p[pos1+1]==1)||(pos1+2<n&&p[pos1+2]==1)||(pos1%2==0&&p[pos1+3]==1))return 1;
				}
			}
			if(pos2!=-1)
			{
				cnt=0;
				for(int i=0;i<pos2;i++)
				{
					cnt+=p[i];
				}
				if(cnt>=(K-1)/2)
				{
					for(int i=1;i<pos2;i++)
					{
						if(p[i]==1&&p[i-1]==1)return 1;
					}
					for(int i=2;i<pos2;i++)
					{
						if(p[i]==1&&p[i-2]==1)return 1;
					}
					for(int i=3;i<pos2;i++)
					{
						if(p[i]==1&&p[i-3]==1)return 1;
					}
					if((pos2>0&&p[pos2-1]==1)||(pos2>1&&p[pos2-2]==1)||(pos2%2!=n%2&&pos2>2&&p[pos2]==1))return 1;
				}
			}
			pos1=-1,pos2=-1;
			cnt2=0;
			for(int i=1;i<n;i++)
			{
				if(p[i]==1&&p[i-1]==1)cnt2++;
			}
			for(int i=2;i<n;i++)
			{
				if(p[i]==1&&p[i-2]==1)cnt2++;
			}
			for(int i=3;i<n;i++)
			{
				if(p[i]==1&&p[i-3]==1)
				{
					cnt2++;
					if(pos1==-1)pos1=i;
					else pos2=i;
				}
			}
			if(cnt2>2||(cnt2==2&&(pos1==-1||pos2==-1||pos1+3!=pos2)))return 1;
			return 0;
		}
		return 0;
	}
	else if(K==2)
	{
		cnt=0;
		for(int i=0;i<n;i++)
		{
			cnt+=p[i];
			if(cnt>=(i+2)/2)return 1;
		}
		cnt=0;
		for(int i=n-1;i>=0;i--)
		{
			cnt+=p[i];
			if(cnt>=(n-i+1)/2)return 1;
		}
		return 0;
	}
	else if(K==3)
	{
		int cnt2=0,pos1=-1,pos2=-1;
		cnt=0;
		for(int i=0;i<n;i++)
		{
			cnt+=p[i];
			if(cnt>=(i+2)/2)
			{
				pos1=i;
				break;
			}
		}
		cnt=0;
		for(int i=n-1;i>=0;i--)
		{
			cnt+=p[i];
			if(cnt>=(n-i+1)/2)
			{
				pos2=i;
				break;
			}
		}
//		cout<<x<<' '<<pos1<<' '<<pos2<<'\n';
		if(pos1!=-1&&pos2!=-1&&pos1+1<pos2)return 1;
		if(pos1!=-1)
		{
			cnt=0;
			for(int i=pos1+1;i<n;i++)
			{
				cnt+=p[i];
				if(cnt>=(i-pos1+1)/2)return 1;
			}
		}
		if(pos2!=-1)
		{
			cnt=0;
			for(int i=pos2-1;i>=0;i--)
			{
				cnt+=p[i];
				if(cnt>=(pos2-i+1)/2)return 1;
			}
		}
		return 0;
	}
	else
	{
		int cnt2=0,pos1=-1,pos2=-1;
		cnt=0;
		for(int i=0;i<n;i++)
		{
			cnt+=p[i];
			if(cnt>=(i+2)/2)
			{
				pos1=i;
				break;
			}
		}
		cnt=0;
		for(int i=n-1;i>=0;i--)
		{
			cnt+=p[i];
			if(cnt>=(n-i+1)/2)
			{
				pos2=i;
				break;
			}
		}
//		if(x==3384)
//		{
//			cout<<x<<' '<<pos1<<' '<<pos2<<' '<<n<<'\n';
//			for(int i=0;i<n;i++)
//			{
//				cout<<p[i]<<' ';
//			}
//			puts("");
//			for(int i=0;i<=n;i++)
//			{
//				for(int j=i+1;j<n;j++)
//				{
//					for(int k=)
//				}
//			}
//		}
		if(pos1!=-1)
		{
			int pos3=-1;
			cnt=0;
			for(int i=pos1+1;i<n;i++)
			{
				cnt+=p[i];
				if(cnt>=(i-pos1+1)/2)
				{
					pos3=i;
					break;
				}
			}
			if(pos3!=-1)
			{
				for(int i=pos3+1;i<n;i++)
				{
					if(p[i]==1)return 1;
				}
			}
			for(int i=pos1+2;i<n;i++)
			{
				if(p[i]==1&&p[i-1]==1)return 1;
			}
			for(int i=pos1+3;i<n;i++)
			{
				if(p[i]==1&&p[i-2]==1)return 1;
			}
			for(int i=pos1+4;i<n;i++)
			{
				if(p[i]==1&&p[i-3]==1)return 1;
			}
			
			if(pos2!=-1)
			{
				for(int i=pos1+1;i<pos2;i++)
				{
					if(p[i]==1)return 1;
				}
			}
		}
		for(int i=0;i<n/2;i++)
		{
			swap(p[i],p[n-1-i]);
		}
		pos1=-1,pos2=-1;
		cnt=0;
		for(int i=0;i<n;i++)
		{
			cnt+=p[i];
			if(cnt>=(i+2)/2)
			{
				pos1=i;
				break;
			}
		}
		cnt=0;
		for(int i=n-1;i>=0;i--)
		{
			cnt+=p[i];
			if(cnt>=(n-i+1)/2)
			{
				pos2=i;
				break;
			}
		}
		if(pos1!=-1)
		{
			int pos3=-1;
			cnt=0;
			for(int i=pos1+1;i<n;i++)
			{
				cnt+=p[i];
				if(cnt>=(i-pos1+1)/2)
				{
					pos3=i;
					break;
				}
			}
			if(pos3!=-1)
			{
				for(int i=pos3+1;i<n;i++)
				{
					if(p[i]==1)return 1;
				}
			}
			for(int i=pos1+2;i<n;i++)
			{
				if(p[i]==1&&p[i-1]==1)return 1;
			}
			for(int i=pos1+3;i<n;i++)
			{
				if(p[i]==1&&p[i-2]==1)return 1;
			}
			for(int i=pos1+4;i<n;i++)
			{
				if(p[i]==1&&p[i-3]==1)return 1;
			}
			if(pos2!=-1)
			{
				for(int i=pos1+1;i<pos2;i++)
				{
					if(p[i]==1)return 1;
				}
			}
		}
//		for(int i=0;i<n;i++)
//		{
//			cout<<p[i]<<' ';
//		}
//		puts("");
		for(int i=2;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==1&&p[i-2]==1)return 1;
		}
		for(int i=3;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==1&&p[i-2]==0&&p[i-3]==1)return 1;
		}
		for(int i=3;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==1&&p[i-3]==1)return 1;
		}
		for(int i=4;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==1&&p[i-3]==0&&p[i-4]==1)return 1;
		}
		for(int i=4;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==1&&p[i-2]==0&&p[i-3]==0&&p[i-4]==1)return 1;
		}
		for(int i=4;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==0&&p[i-3]==1&&p[i-4]==1)return 1;
		}
		for(int i=5;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==1&&p[i-3]==0&&p[i-4]==0&&p[i-5]==1)return 1;
		}
		for(int i=5;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==0&&p[i-3]==1&&p[i-4]==0&&p[i-5]==1)return 1;
		}
		for(int i=6;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==1&&p[i-2]==0&&p[i-3]==0&&p[i-4]==0&&p[i-5]==1&&p[i-6]==1)return 1;
		}
		for(int i=7;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==0&&p[i-3]==1&&p[i-4]==0&&p[i-5]==0&&p[i-6]==1&&p[i-7]==1)return 1;
		}
		for(int i=7;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==1&&p[i-2]==0&&p[i-3]==0&&p[i-4]==1&&p[i-5]==0&&p[i-6]==0&&p[i-7]==1)return 1;
		}
		for(int i=7;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==0&&p[i-2]==1&&p[i-3]==0&&p[i-4]==0&&p[i-5]==0&&p[i-6]==1&&p[i-7]==1)return 1;
		}
		for(int i=7;i<n;i++)
		{
			if(p[i]==1&&p[i-1]==1&&p[i-2]==0&&p[i-3]==0&&p[i-4]==0&&p[i-5]==1&&p[i-6]==0&&p[i-7]==1)return 1;
		}
		return 0;
	}
}
int median(int n,int K,vector<int> a)
{
	p.assign(n,0);
	s.assign(n,0);
	int l=1,r=n,ans=0;
	while(l<=r)
	{
		int mid=l+r>>1;
		for(int i=0;i<n;i++)
		{
			p[i]=(a[i]>=mid);
		}
		if(check(mid,K))l=mid+1,ans=mid;
		else r=mid-1;
	}
//	for(int i=0;i<n;i++)
//	{
//		p[i]=(a[i]>=78);
//	}
//	check(78,K);
//	for(int i=0;i<n;i++)
//	{
//		p[i]=(a[i]>=79);
//	}
//	check(79,K);
	return ans;
}
//#include <bits/stdc++.h>
//#include "median.h"
//
//signed main() {
//	freopen("median4.in","r",stdin);
//    int c, t;
//    std::cin >> c >> t;
//    init(c, t);
//    for (int _ = 0; _ < t; _++) {
//        int n, k;
//        std::cin >> n >> k;
//        if(_==16)cout<<k<<'\n';
//        std::vector<int> a(n);
//        for (int i = 0; i < n; i++) std::cin >> a[i];
//        std::cout << median(n, k, a) << '\n';
//    }
//    return 0;
//}
posted @ 2026-07-28 16:20  MCYYDS  阅读(6)  评论(0)    收藏  举报