Time Limits: 10000 ms Memory Limits: 524288 KB Detailed Limits
Description
chnlich 非常喜欢玩三国志这款游戏,并喜欢用一些策略出奇制胜。现在,他要开始征服世界的旅途了。他的敌人有N 座城市和N 个太守, N个城市可以看作在二维平面上的N 个点。N 座城市的标号为0,1,2,......,N-1。第i 座城市的坐标为(Xi,Yi),镇守这座城市的太守的能力值为Zi。
chnlich 每次会选择一个边平行于坐标轴的矩形区域,并奇袭其中太守能力值第K小的城市(奇袭结束之后城市与太守依然存在)。
不过,他的敌人经常会偷偷交换两座城市的太守,防止弱点被chnlich 发现。
现在,chnlich 想要知道,每次奇袭时他的敌人的能力值。
Input
输入的第一行包含两个整数 N,M,N 表示城市与太守的个数,M 表示接下来发生了 M 个事件。
输入的第二行到第 N+1行,每行包含三个整数,第 i+2行的三个整数依次表示编号为 i 的城市的 Xi,Yi,Zi,含义如题所述。
输入的第 N+2行到第 N+M+1行,每行有两种可能形式:
第一种
QUERY x0 y0 x1 y1 k
表示 chnlich 询问一个相对顶点为(x0,y0),(x1,y1)的矩形中,第 k 小能力值太
守的能力值。
第二种
SWAP x y
表示 chnlich 的敌人交换了编号为 x 和 y 两座城市的太守。
Output
对于每一个 QUERY,输出一行。
若不存在第 k 小能力值的太守,输出"It doesn't exist."(不包含引号)。
否则输出一个整数,表示矩形内能力值第 k 小太守的能力值。
Sample Input
3 5 1 1 1 2 2 2 3 3 3 QUERY 1 1 3 3 3 SWAP 0 1 QUERY 2 2 4 4 1 SWAP 2 2 QUERY 2 2 3 3 3
Sample Output
3 1 It doesn't exist.
Data Constraint
Hint
对于100%的数据,N<=60000,M<=10000,0<=Xi,Yi,Zi<=10^9,k<=10^9,保证所有操作均合法。
题目大意:
在平面内有一些有权点。有m个操作,分为两种,第一种:给定一个矩形区域,问区域内所有点的第k小权值。
第二种:swap x点和y点的权值。
题解:
10000ms = 10秒。暴力即可。
把所有点按x坐标升序。
对于第二种操作直接swap , 第一种则先找x坐标在范围内的点,放在一个数组里。然后O(n)找第k小。
O(n)找序列内的第k小值:
快排。
在快排的基础上加点东西。
每次我们选取一个基准值。把小于此的排在左边 , 大于的在右边。
我们现在找第p小。
如果第p小在左边,排序左边。否则排序右边。
注意:看p是否在左边只需判断p <= j-l+1
但是看p是否在右边不能直接判断 p > j-l+1,因为i和j之间可能还有元素(狭小缝隙),直接到右边会将其忽略。要判断 p > i-l
如果狭缝正有我们要找的呢? 出现狭缝 :比如序列 1222234 。i在位置2停下 , j在位置5停下。
如果是这样的话 , if语句就会咔嚓掉前面两条判断 ,到第三条语句, 直接更新ans (如下码) 。
还有一种到第三条语句的可能,那就是 递归完了回来 , 但是之前如果答案已经更新 , 再到这里没有意义。return掉。
也就是说,ans只会在狭缝的情况 , 或递归不下去(如下)的情况 , 会更新。
分析时间复杂度:
第一层n,第二层只有n/2 ,然后n/4 , n/8... O(2n)
void query(ll L[],ll l,ll r,ll p)
{
if(l > r) return ;
ll i=l,j=r;
ll mid = L[(l+r)/2];
while(i<=j)
{
while(L[i] < mid) ++i;
while(L[j] > mid) --j;
if(i<=j)
{
swap(L[i],L[j]);
++i,--j;
}
}
if(p > i - l) query(L , i , r , p - (i-l));
if(j - l + 1>=p) query(L , l,j,p);
if(!ans) ans = L[l+p-1];
}
程序代码:
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define mcy(a,b) memcpy(a,b,sizeof(a))
#define ll long long
#pragma GCC optimize(3)
#define re register
#define inf 2000000000
#define N 60010
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
struct point
{ll x,y,z,id;}a[N],b[N],c[N];
ll n,m,i,j,k,t,ans;
ll fo[N] ,sa[N];
char ch;
bool cmp(point x,point y)
{return x.x < y.x;}
bool tmp(point x,point y)
{return x.z < y.z;}
void init()
{
ll cnt=0;
sort(a+1,a+1+n , tmp);
for(ll i=1;i<=n;i++)
{
if(a[i].z!=a[i-1].z) ++cnt;
fo[cnt] = a[i] . z;
a[i] . z = cnt;
}
sort(a+1,a+1+n,cmp);
for(ll i=1;i<=n;i++) sa[a[i].id] = i;
return ;
}
ll find1(ll x)
{
ll l=0,r=n,p=-1;
while(l<=r)
{
ll mid=(l+r)/2;
if(a[mid] . x >= x)
{
p = mid;
r = mid - 1;
}else l = mid+1;
}
return p ;
}
ll find2(ll x)
{
ll l=0,r=n,p=-1;
while(l<=r)
{
ll mid=(l+r)/2;
if(a[mid] . x <= x)
{
p = mid;
l = mid+1;
}else r = mid - 1;
}
return p;
}
ll L[N] , len;
void query(ll L[],ll l,ll r,ll p)
{
if(l > r) return ;
ll i=l,j=r;
ll mid = L[(l+r)/2];
while(i<=j)
{
while(L[i] < mid) ++i;
while(L[j] > mid) --j;
if(i<=j)
{
swap(L[i],L[j]);
++i,--j;
}
}
if(p > i - l) query(L , i , r , p - (i-l));
if(j - l + 1>=p) query(L , l,j,p);
if(!ans) ans = L[l+p-1];
}
int main()
{
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)
scanf("%lld%lld%lld\n",&a[i].x,&a[i].y,&a[i].z),a[i].id = i;
init();
for(i=1;i<=m;i++)
{
scanf("%c" , &ch);
if(ch == 'Q')
{
ll x1,y1,x2,y2,k;
scanf("UERY %lld%lld%lld%lld%lld\n",&x1,&y1,&x2,&y2,&k);
if(x1 > x2) swap(x1,x2);
if(y1 > y2) swap(y1,y2);
ll st=find1(x1),ed=find2(x2);
if(st == -1 || ed == -1) {printf("It doesn't exist.\n");continue;}
len=0;
for(j=st;j<=ed;j++)
if(a[j].y>=y1 && a[j].y<=y2) L[++len] = a[j].z;
if(len < k )printf("It doesn't exist.\n");else
{
ans=0;
query(L,1,len,k);
printf("%lld\n",fo[ans] );
if(fo[ans] == 62872239)
{
len = 0;
}
}
}
else
{
ll x,y;
scanf("WAP %lld%lld\n",&x,&y);
++x;++y;
swap(a[sa[x]].z , a[sa[y]].z);
}
}
}