(線段樹 + 離散化 ) hdu 3627 Giant For

來源:互聯網
上載者:User
Giant For

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1397    Accepted Submission(s): 261

Problem DescriptionIt is known to us all that YY and LMY are mathematics lovers. They like to find and solve interesting mathematic problems together. Now LMY designs a game for matrix. There is a large matrix whose rows and columns are both not more than 1000000000. And there are three operations for the matrix:
1) add: Mark an element in the matrix. It is guaranteed that the element has not been marked before.
2) remove: Delete an element’s mark. It is guaranteed that the element has been marked before.
3) find: For a given element’s row and column, return a marked element’s row and column, where the marked element’s row and column are larger than the given element’s row and column respectively. If there are multiple solutions, return the element whose row is the smallest; and if there are still multiple solutions, return the element whose column is the smallest. If there is no solution, return -1.
LMY lets YY develop a program to solve the problem. Could you also develop a program to solve the problem? 

 

InputThe input consists of multiple test cases. For each test case, the first line contains only one integer n. n ≤ 200000. Each of the next n lines describes an operation. There is a blank line between two consecutive test cases.
End of input is indicated by a line containing a zero. 

 

OutputStart each test case with "Case #:" on a single line, where # is the case number starting from 1. For each “find” operation, output the result. The format is showed as sample output. There is a blank line between two consecutive test cases. 

 

Sample Input
5add 48 1add 25 69add 88 52remove 25 69add 23 8910add 47 23find 66 83find 27 73add 84 97find 10 58remove 47 23add 41 89remove 41 89find 65 68add 25 410
Sample Output
Case 1:Case 2:-1-184 9784 97
SourceThe 35th ACM/ICPC Asia Regional Tianjin Site —— Online Contest 2010天津網路預選賽1007題目ps:當時沒學線段樹,一看資料這麼大就蒙了,現在學了線段樹就做了起來。效率還不錯1548ms AC線段樹的資料:請參考http://blog.csdn.net/Hashmat/archive/2010/09/28/5911369.aspx/*</p><p>題目大意:不超過*1000000000的矩陣,三個操作。add 插入(xi,yi);remove 移除 (xi,yi);find 尋找(>xi,>yi)的最小值<br />題目解答:n=1000000000 太大超過 int 的範圍<br />:op_num(運算元) = 200000 也就是最多有op_num對數值 所以離散成 hash[op_num]然後再用線段樹統計</p><p>Problem : 3627 ( Giant For ) Judge Status : Accepted<br />RunId : 3007530 Language : C++ Author : wawadimu<br />Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta<br />*/<br />#include<iostream><br />#include<algorithm><br />using namespace std;</p><p>#define N 200010</p><p>//運算元組<br />char op[N][7];</p><p>//原數組,排序數組,離散後數組</p><p>struct node<br />{<br />int row,col;<br />}res[N],tmp[N],hash[N];</p><p>// 線段樹<br />struct tr<br />{<br />int l,r,max_col;<br />}tree[3*N];</p><p>//按行升序排列<br />int cmp( const node &a , const node &b)<br />{<br />if( a.row != b.row ) return a.row < b.row;<br />else return a.col < b.col ;<br />}</p><p>//在區間[L,R]內尋找p的次序<br />int query(node p , int L , int R);<br />//建立線段樹<br />void built(int l, int r , int num);<br />//更新區間[cnt,cnt]<br />void insert(node p, int cnt , int num);<br />//移除區間[cnt,cnt];<br />void remove(node p, int cnt ,int num);<br />//尋找區間[L,R]內比L大的節點<br />int find(node p , int L ,int R , int num);</p><p>int main()<br />{<br />freopen("3627.txt","r",stdin);<br />int n;<br />int i,j,k;<br />int c=1;<br />while(scanf("%d",&n)!=EOF && n!=0)<br />{<br />if( c != 1) printf("/n");<br />printf("Case %d:/n",c++);<br />for(i=1; i<=n; i++)<br />{<br />scanf("%s%d%d",op[i], &res[i].row, &res[i].col);<br />tmp[i].row=res[i].row; tmp[i].col=res[i].col;<br />}<br />sort(tmp+1,tmp+n+1,cmp);//排序<br />k=0;<br />tmp[0].col=-N; tmp[0].row=-N;<br />for(i=1; i<=n; i++)//離散<br />{<br />if( tmp[i].row == tmp[i-1].row && tmp[i].col == tmp[i-1].col) continue;<br />else<br />{ //cout<<tmp[i].row<<"->"<<tmp[i].col<<" ";<br />hash[++k].col=tmp[i].col;<br />hash[k].row=tmp[i].row;<br />}<br />}<br />//cout<<k<<endl;<br />built(1 , k , 1 );<br />for(i=1; i<=n; i++)<br />{<br />int cnt=query( res[i] , 1 , k); //尋找res[i]在離散後的數組的位置hash[cnt]<br />//cout<<cnt<<" ";<br />if( strcmp( op[i] ,"add") == 0) insert( res[i] , cnt ,1 );<br />else if(strcmp( op[i] , "remove") == 0) remove( res[i] , cnt ,1 );<br />else {<br />int ans=find( res[i] , cnt , k , 1 );//找到返回區間值[ans,ans],否則返回-1<br />if( ans ==-1 ) printf("-1/n");<br />else printf("%d %d/n",hash[ans].row,hash[ans].col);<br />}<br />}<br />}<br />return 0;<br />}<br />void built( int l , int r , int num)//建立單點的區間<br />{<br />tree[num].l=l; tree[num].r= r; tree[num].max_col=0;<br />//cout<<num<<" :"<<l<<"->"<<r<<" ";<br />if(l<r)<br />{<br />int m=( l + r ) >> 1;<br />built( l , m , 2*num );<br />built( m+1 , r, 2*num+1 );//m+1<br />}<br />}<br />int query(node p , int L , int R)<br />{<br />int l=L , r=R ;<br />int t = p.row;<br />//<br />//由於可以出現行重疊的情況,所以尋找比他row大的數字,然後反推比較確定值的位置<br />//<br />while( l <= r)<br />{<br />int mid=( l + r ) >> 1;<br />if( t >= hash[mid].row )<br />l= mid + 1;<br />else r= mid -1;<br />}<br />//反向比較,確定位置<br />while(--l)<br />{<br />if(hash[l] .col == p.col )<br />break;<br />}<br />return l;<br />}<br />void insert( node p, int cnt , int num)<br />{<br />if( tree[num].l == tree[num].r )//葉子節點,插入<br />{<br />//cout<<tree[num].l<<"->"<<p.col<<" ";<br />tree[num].max_col = p.col;<br />return ;<br />}<br />//cout<<num<<" ";<br />int mid=( tree[num].l + tree[num].r ) >> 1;<br />if( cnt <= mid ) insert( p , cnt , 2*num );<br />else insert( p , cnt , 2*num + 1);<br />//父親節點儲存子樹y的最大值,有利於降低尋找的效率<br />tree[num].max_col = tree[2*num].max_col > tree[2*num+1].max_col ? tree[2*num].max_col : tree[2*num+1].max_col;<br />}<br />void remove( node p, int cnt , int num)<br />{<br />if( tree[num].l == tree[num].r )<br />{<br />//cout<<tree[num].l<<"->"<<p.col<<" ";<br />tree[num].max_col = 0;<br />return ;<br />}<br />//cout<<cnt<<num<<" ";<br />int mid=( tree[num].l + tree[num].r ) >> 1;<br />if( cnt <= mid ) remove( p , cnt , 2*num );<br />else remove( p , cnt , 2*num + 1);<br />}<br />int find( node p , int L , int R ,int num)<br />{<br />int tmp;<br />if( tree[num].max_col < p.col ) return -1;<br />if( tree[num].l == tree[num].r )<br />{//tree[num].max_col > p.col && tree[num].l > L cout<<tree[num].l<<">"<<L<<" ";<br />if( hash[tree[num].l].row > p.row && hash[tree[num].r].col > p.col )//這裡比較實際值的大小不是離散值大小,因為這裡WA了.<br />{</p><p>return tree[num].l;<br />}<br />else return -1;<br />}<br />int mid = ( tree[num].l + tree[num].r ) >> 1;<br />//<br />//如果覆蓋兩個子領域,先找左區間是否有符合的值,然後尋找右區間的情況<br />//<br />if( L < mid )<br />{<br />//cout<<2*num<<" ";<br /> tmp = find( p, L , R, 2*num );<br />if( tmp != -1 ) return tmp;<br />}<br />if( R >= mid )<br />{<br />//cout<<2*num+1<<" ";<br />tmp=find( p, L , R, 2*num + 1 );<br />if( tmp != -1 ) return tmp;<br />}<br />return -1;<br />}<br />

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.