天津网络预选赛 1007-Giant_For(线段树+set)

已行[xi,xj](0<xi<=xj<cnt-1,cnt表示离散化后的行坐标个数)区间内最大的列为键值构建线段树,再以set维护每个点中的y值。find的话查找【x+1,n】中最小的点,该点的最大列值是大于y的;然后返回的是x的位置,再从x的set里取出最小的一个比y大的值!

 

 

#include<iostream>

#include<algorithm>

#include<string.h>

#include<set>

using namespace std;

 

struct Seg

{

int l,r,max_col;

};

struct Q

{

char ch[8];

int row,col;

};

Q q[200010];

Seg seg[200010*3];

int dia[200010];

set<int> S[200010];

int n;

 

void maketree(int l,int r,int c)

{

seg[c].l=l;

seg[c].r=r;

seg[c].max_col=0;

if(l==r) return ;

int mid=(l+r)>>1;

maketree(l,mid,c*2);

maketree(mid+1,r,c*2+1);

}

 

 

void updata(int pos,int c,int col)

{

if(seg[c].l==seg[c].r) 

{

seg[c].max_col=col;

return ;

}

int mid=(seg[c].l+seg[c].r)>>1;

if(pos<=mid)

updata(pos,c*2,col);

else

updata(pos,c*2+1,col);

seg[c].max_col=max(seg[c*2].max_col,seg[c*2+1].max_col);

}

 

// int find(int l,int r,int num)

// {

// int mid;

// while(l<=r)

// {

// mid=(l+r)>>1;

// if(dia[mid]==num) return mid;

// else if(dia[mid]>num) 

// r=mid-1;

// else

// l=mid+1;

// }

// }

 

int qurey(int l,int r,int c,int col)

{

if(seg[c].max_col<=col||seg[c].r<l||seg[c].l>r)

return -1;

if(seg[c].l==seg[c].r)

return seg[c].l;

int mid=(seg[c].l+seg[c].r)>>1;

if(r<=mid)

return qurey(l,r,c*2,col);

else if(l>mid)

return qurey(l,r,c*2+1,col);

else

{

int temp=qurey(l,mid,c*2,col);

if(temp==-1)

return qurey(mid+1,r,c*2+1,col);

else 

return temp;

}

}

 

void init()

{

for(int i=1;i<=n;i++)

if(q[i].ch[0]=='f')

printf("-1/n");

printf("/n");

}

int main()

{

int i,j,cas=1;

while(scanf("%d",&n)!=EOF)

{

if(n==0) return 0;

if(cas!=1)

printf("/n");

int cnt=0;

for(i=1;i<=n;i++)

{

scanf("%s %d %d",&q[i].ch,&q[i].row,&q[i].col);

{

if(q[i].ch[0]=='a')

{

dia[cnt++]=q[i].row;

}

}

}

printf("Case %d:/n",cas++);

if(cnt==0) {

init();

continue;

}

sort(dia,dia+cnt);

int c=0;

for(i=0;i<cnt;i++)

{

S[c].clear();

S[c].insert(0);

dia[c++]=dia[i];

while(i+1<cnt&&dia[i+1]==dia[i])

i ++;

}

cnt=c;

set<int>::iterator it;

maketree(0,cnt-1,1);

for(i=1;i<=n;i++)

{

if(q[i].ch[0]=='a')

{

int pos=lower_bound(dia,dia+cnt,q[i].row)-dia;

it = S[pos].lower_bound(q[i].col);

if(it==S[pos].end())

updata(pos,1,q[i].col);

S[pos].insert(q[i].col);

}

else if(q[i].ch[0]=='r')

{

int pos=lower_bound(dia,dia+cnt,q[i].row)-dia;

it = S[pos].find(q[i].col);

it++;

if(it==S[pos].end())

{

it--;

it--;

updata(pos,1,*it);

}

S[pos].erase(q[i].col);

}

else

{

int pos=lower_bound(dia,dia+cnt,q[i].row+1)-dia;

int respos=qurey(pos,cnt-1,1,q[i].col);

if(respos==-1)

printf("-1/n");

else

{

 

it=S[respos].lower_bound(q[i].col+1);

printf("%d %d/n",dia[respos],(*it));

}

}

}

}

return 0;

}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值