洛谷 P6325 [COCI2006-2007#4] ISPITI
\(\texttt{Description}\)
有 \(n\) 个操作:
\(\texttt{D }x\texttt{ }y\):插入一个 \((x,y)\) 的元素(不会有重复的元素)。
\(\texttt{P }i\):查询在所有 \(x\ge x_i,y\ge y_i\) 的元素中(不包括本身),\(y\) 最小的元素的编号(输入顺序),若 \(y\) 相同,则输出 \(x\) 最小的。
\(1\le n\le 2\times 10^5\),\(1\le x,y\le 2\times 10^9\)。
\(\texttt{Solution}\)
先将所有操作离线,对 \(y\) 离散化。用 set 维护每个 \(y\) 上 \(x\) 的情况。考虑先找到最小的 \(y\),再找到对应的 \(x\)。
对 \(\texttt{P}\) 操作分类讨论(设答案为 \(j\)):
-
\(y_j=y_i\),由于不包括本身,需要这种情况下寻找 \(x_j>x_i\) 的最小的 \(j\)。用
set的upper_bound即可。 -
\(y_j>y_i\),此时不难发现答案有单调性,即对于 \(k\) 若 \(y\in[y_i+1,k]\) 有解,则 \(y\in[y_i+1,k+1]\) 有解;反之无解,则 \(y\in [y_i+1,k-1]\) 无解。二分 \(y_j\),判断 \([y_i+1,y_j]\) 中是否有解。具体来讲,若其中最大的 \(x\) 满足 \(x\ge x_i\),则有解,否则无解。再用线段树维护最大的 \(x\) 即可。找到 \(y_j\) 以后,再用
lower_bound查询 \(x_j\ge x_i\) 最小的 \(j\) 即可。
对于 \(\texttt{D}\) 操作,先在 set 上插入,如果能更新最大值就更新。
时间复杂度为 \(\mathcal{O}(n\log^2n)\),空间复杂度为 \(\mathcal{O}(n)\)。
\(\texttt{Code}\)
$\texttt{Click For Code}$
#include<bits/stdc++.h>
#define N 200005
#define ls x<<1
#define rs x<<1|1
using namespace std;
int n,tot,num,mx[N<<2];
set<int>s;
set<pair<int,int>>Y[N];
map<int,int>mp;
char c;
pair<int,int>stu[N];
struct data{
int op,x,y;
}p[N];
void modify(int x,int l,int r,int k,int v){
if(l^r){
int m=(l+r)>>1;
if(k<=m){
modify(ls,l,m,k,v);
}else{
modify(rs,m+1,r,k,v);
}
mx[x]=max(mx[ls],mx[rs]);
}else{
mx[x]=v;
}
}
bool query(int x,int l,int r,int ql,int qr,int y){
if(ql<=l&&r<=qr){
return mx[x]>=y;
}
int m=(l+r)>>1;
bool ret=0;
if(ql<=m){
if(query(ls,l,m,ql,qr,y)){
return 1;
}
}
if(qr>m){
ret|=query(rs,m+1,r,ql,qr,y);
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1,x,y;i<=n;++i){
scanf(" %c",&c);
if(c^'P'){
scanf("%d%d",&x,&y);
p[i]={0,x,y};
stu[++num]=make_pair(x,y);
s.insert(y);
}else{
scanf("%d",&x);
p[i]={1,stu[x].first,stu[x].second};
}
}
for(int i:s){
mp[i]=++tot;
}
for(int i=1,x,y,j=0;i<=n;++i){
x=p[i].x;
y=mp[p[i].y];
if(p[i].op){
auto it=Y[y].upper_bound(make_pair(x,1e9));
if(it!=Y[y].end()){
printf("%d\n",it->second);
}else{
int l=y+1,r=tot,f=0;
while(l<=r){
int m=(l+r)>>1;
if(query(1,1,tot,y+1,m,x)){
r=(f=m)-1;
}else{
l=m+1;
}
}
if(f){
printf("%d\n",Y[f].lower_bound(make_pair(x,0))->second);
}else{
puts("NE");
}
}
}else{
if(!Y[y].size()||x>Y[y].rbegin()->first){
modify(1,1,tot,y,x);
}
Y[y].insert(make_pair(x,++j));
}
}
}

浙公网安备 33010602011771号