AT_abc237_g [ABC237G] Range Sort Query 题解
前置知识
解法
观察到只有 \(=x\) 的位置才是重要的,而其他位置上的数具体是什么并不重要,我们只需要关注其大小关系。
第一遍将 \(\ge x\) 的数看做 \(1\),将 \(<x\) 的数看做 \(0\)。第二遍将 \(>x\) 的数看做 \(1\),将 \(\le x\) 的数看做 \(1\)。
此时排序操作就容易通过查询 \(1\) 的个数后进行推平来维护了,可以使用珂朵莉树/线段树实现。
查询时只需要找到一个位置使得第一遍中是 \(1\) 而第二遍中是 \(0\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
int a[200010],b[200010],c[200010];
struct ODT
{
struct node
{
int l,r;
mutable int col;
bool operator < (const node &another) const
{
return l<another.l;
}
};
set<node>s;
void init(int n,int a[])
{
for(int i=1;i<=n;i++)
{
s.insert((node){i,i,a[i]});
}
}
set<node>::iterator split(int pos)
{
set<node>::iterator it=s.lower_bound((node){pos,0,0});
if(it!=s.end()&&it->l==pos)
{
return it;
}
it--;
if(it->r<pos)
{
return s.end();
}
int l=it->l,r=it->r,col=it->col;
s.erase(it);
s.insert((node){l,pos-1,col});
return s.insert((node){pos,r,col}).first;
}
void assign(int l,int r,int col)
{
set<node>::iterator itr=split(r+1),itl=split(l);
s.erase(itl,itr);
s.insert((node){l,r,col});
}
int query(int l,int r)
{
set<node>::iterator itr=split(r+1),itl=split(l);
int ans=0;
for(set<node>::iterator it=itl;it!=itr;it++)
{
ans+=it->col*(it->r-it->l+1);
}
return ans;
}
int ask(int pos)
{
set<node>::iterator it=s.lower_bound((node){pos,0,0});
if(it!=s.end()&&it->l==pos)
{
return it->col;
}
it--;
return it->col;
}
}O[2];
int main()
{
// #define Isaac
#ifdef Isaac
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n,m,x,pd,l,r,i,j;
cin>>n>>m>>x;
for(i=1;i<=n;i++)
{
cin>>a[i];
b[i]=(a[i]>=x);
c[i]=(a[i]>x);
}
O[0].init(n,b);
O[1].init(n,c);
for(i=1;i<=m;i++)
{
cin>>pd>>l>>r;
if(pd==1)
{
for(j=0;j<=1;j++)
{
pd=O[j].query(l,r);
O[j].assign(l,r-pd,0);
O[j].assign(r-pd+1,r,1);
}
}
else
{
for(j=0;j<=1;j++)
{
pd=O[j].query(l,r);
O[j].assign(l,l+pd-1,1);
O[j].assign(l+pd,r,0);
}
}
}
for(i=1;i<=n;i++)
{
if(O[0].ask(i)==1&&O[1].ask(i)==0)
{
cout<<i<<endl;
}
}
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18640631,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。