码迷,mamicode.com
首页 > 其他好文 > 详细

sdut 2159 Ivan comes again!(2010年山东省第一届ACM大学生程序设计竞赛) 线段树+离散

时间:2015-04-21 14:36:20      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

先看看上一个题:

题目大意是: 矩阵中有N个被标记的元素,然后针对每一个被标记的元素e(x,y),你要在所有被标记的元素中找到一个元素E(X,Y),使得X>x并且Y>y,如果存在多个满足条件的元素,先比较X,选择X最小的那个,如果还是有很多满足条件的元素,再比较Y,选择Y最小的元素,如果不存在就输出两个-1;

分析: 直接暴力就行了

 

这个题目大意:

这个题是上个题的坚强版,每次会增加或减少一个点,仍然找到一个元素E(X,Y),使得X>x并且Y>y;

最多有200000次操作,每次只能是O(logn)的查询,行有1000000000之大,但是最多只会出现200000个不同的行,所以要离散化一下。然后对于每行的所有列用set去存,用线段树来维护每一行的出现的最大列,具体看代码吧

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<set>
  7 #include<queue>
  8 #include<stack>
  9 #define MAXN 200010
 10 
 11 using namespace std;
 12 
 13 int Max[MAXN<<2], b[MAXN], c[MAXN], cnt;
 14 set<int>sy[MAXN];
 15 struct node
 16 {
 17     int x, y, flag;
 18 } n[300000];
 19 void PushUp(int root)
 20 {
 21     Max[root]=max(Max[root*2],Max[root*2+1]);
 22 }
 23 void Update(int p, int x, int L, int R, int root) //a[p]=x,并且更新最大值
 24 {
 25     if(L==R)
 26     {
 27         Max[root]=x;
 28         return ;
 29     }
 30     int mid=(L+R)/2;
 31     if(p<=mid) Update(p,x,L,mid,root*2);
 32     else Update(p,x,mid+1,R,root*2+1);
 33     PushUp(root);
 34 }
 35 int Query(int num, int post_ll, int L, int R, int root)//从post_ll这个位置开始向右查找,返回大于等于num的位置下表
 36 {
 37     if(L==R)
 38     {
 39         if(Max[root]>=num) return L;
 40         else return -1;
 41     }
 42     int ans=-1, mid=(L+R)/2;
 43     if(post_ll<=mid&&Max[root*2]>=num) ans=Query(num,post_ll,L,mid,root*2);
 44     if(ans!=-1) return ans;
 45     if(Max[root*2+1]>=num) ans=Query(num,post_ll,mid+1,R,root*2+1);
 46     return ans;
 47 }
 48 
 49 int BS1(int x)
 50 {
 51     int low=0, high=cnt, mid;
 52     while(low<=high)
 53     {
 54         mid=low+high>>1;
 55         if(c[mid]==x) return mid;
 56         else if(c[mid]>x) high=mid-1;
 57         else low=mid+1;
 58     }
 59 }
 60 int BS2(int x)
 61 {
 62     int low=0, high=cnt, mid, ans=-1;
 63     while(low<=high)
 64     {
 65         mid=low+high>>1;
 66         if(c[mid]>x)
 67         {
 68             ans=mid;
 69             high=mid-1;
 70         }
 71         else low=mid+1;
 72     }
 73     return ans;
 74 }
 75 void init(int nn)
 76 {
 77     for(int i=0; i<nn; i++)
 78         sy[i].clear();
 79     memset(Max,-1,sizeof(Max));
 80 }
 81 int main()
 82 {
 83     int nn, x, tot, ans, cas=0;
 84     char cmd[20];
 85     while(scanf("%d",&nn)!=EOF&&nn)
 86     {
 87         cnt=tot=0;
 88         init(nn);
 89         for(int i=0; i<nn; i++)
 90         {
 91             scanf("%s%d%d",cmd,&n[i].x,&n[i].y);
 92             if(!strcmp(cmd,"add"))
 93             {
 94                 n[i].flag=1;
 95                 b[tot++]=n[i].x;
 96             }
 97             else if(!strcmp(cmd,"find"))
 98                 n[i].flag=2;
 99             else n[i].flag=3;
100         }
101         sort(b,b+tot);
102         c[0]=b[0];
103         for(int i=1; i<tot; i++)
104         {
105             if(b[i]!=b[i-1])
106                 c[++cnt]=b[i];
107         }//离散化
108         printf("Case %d:\n",++cas);
109         for(int i=0; i<nn; i++)
110         {
111             if(n[i].flag==1)
112             {
113                 x=BS1(n[i].x);
114                 sy[x].insert(n[i].y);
115                 Update(x,*(--sy[x].end()),0,cnt,1);
116             }
117             else if(n[i].flag==2)
118             {
119                 x=BS2(n[i].x);
120                 if(x==-1)
121                 {
122                     puts("-1");
123                     continue ;
124                 }
125                 ans=Query(n[i].y+1,x,0,cnt,1);
126                 if(ans==-1) printf("-1\n");
127                 else printf("%d %d\n",c[ans],*(sy[ans].lower_bound(n[i].y+1)));
128             }
129             else
130             {
131                 x=BS1(n[i].x);
132                 sy[x].erase(n[i].y);
133                 if(!sy[x].size())
134                 {
135                     Update(x,-1,0,cnt,1);
136                 }
137                 else Update(x,*(--sy[x].end()),0,cnt,1);
138             }
139         }
140         printf("\n");
141     }
142     return 0;
143 }

 

sdut 2159 Ivan comes again!(2010年山东省第一届ACM大学生程序设计竞赛) 线段树+离散

标签:

原文地址:http://www.cnblogs.com/tsw123/p/4444187.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!