Codeforces Round #724 (Div. 2) D. Omkar and Medians (权值线段树,动态开点)
-
题意:有长度为\(k\)的数组\(b\),问你是否能构造一个长度为\(2k-1\)的数组\(a\),使得对于\(a_1,a_2,...,a_{2i-1}\),其中位数是\(b_i\).
-
题解:首先要能看出一个结论,即对于一个有序的序列,我们在其中位数左边添加两个数,会使得中位数的位置左移一个,在其右边添加两个会使得中位数的位置右移一个,左右各添一个位置不变.然后根据\(b_i\)一个一个线性构造\(a\),不难推出唯一不合法的情况为对于\(j\le i\),有\(b_j>min(b_{i},b_{i+1}),b_j<max(b_i,b_{i+1})\).那么就可以用线段树或者set来维护,本题给出的是权值线段树动态开点的写法.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} #define int long long int n; ll b[N]; int rt; int idx; int ls[N<<4],rs[N<<4]; void update(int &u,int l,int r,int x){ if(!u) u=++idx,ls[u]=rs[u]=0; if(l==r) return; int mid=(l+r)>>1; if(x<=mid) update(ls[u],l,mid,x); else update(rs[u],mid+1,r,x); } int query(int u,int l,int r,int x,int y){ if(x>y) return 0; if(!u) return 0; if(l>=x && r<=y) return 1; int mid=(l+r)>>1; if(x<=mid && query(ls[u],l,mid,x,y)) return 1; if(y>mid && query(rs[u],mid+1,r,x,y)) return 1; return 0; } signed main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int _; cin>>_; while(_--){ cin>>n; for(int i=1;i<=n;++i){ cin>>b[i]; } rt=0; idx=0; update(rt,-1e9,1e9,b[1]); bool flag=true; for(int i=2;i<=n;++i){ if(query(rt,-1e9,1e9,min(b[i],b[i-1])+1,max(b[i],b[i-1])-1)!=0){ flag=false; break; } update(rt,-1e9,1e9,b[i]); } if(flag) cout<<"YES\n"; else cout<<"NO\n"; } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮