POJ 2828 Buy Tickets(線段樹單點)
阿新 • • 發佈:2017-09-16
== fun time str 每次 cout cti sta 新的
https://vjudge.net/problem/POJ-2828
題目意思:有n個數,進行n次操作,每次操作有兩個數pos, ans。pos的意思是把ans放到第pos 位置的後面,pos後面的數就往後推一位。最後輸出每個位置的ans。
思路:根據題 目可知,最後插入的位置的數才是最終不變的數,所以可以從最後的輸入作第1個放入,依此類推,倒插入。在插入時也有一定的技術,首先創建一棵空線段樹時,每個節點記錄當前範圍內有多少個空位置。在插入時,要註意,一個數放入之後那麽這個位置就不用管了,那麽樹中所有的空位置就是余下的數所對應的位置,也就是把余下的數又可以看作是一個新的集合。那麽每次插入都是當前集合的第1次放。
1 #include <iostream> 2 #include <algorithm> 3 #include <string> 4 #include <sstream> 5 #include <set> 6 #include <vector> 7 #include <stack> 8 #include <map> 9 #include <queue> 10 #include <deque> 11 #include <cstdlib> 12 #include <cstdio> 13#include <cstring> 14 #include <cmath> 15 #include <ctime> 16 #include <functional> 17 // #include <bits/stdc++.h> 18 using namespace std; 19 20 int n,ans[1000000]; 21 22 struct node 23 { 24 int n,val; 25 }a[1000000]; 26 27 struct tree 28 { 29 int l,r,n; 30 }b[1000000]; 31 32 voidinit() 33 { 34 int i,j,k; 35 for(k=1;k<n;k<<=1); 36 for(i=k;i<2*k;i++) 37 { 38 b[i].l=b[i].r=i-k+1; 39 b[i].n=1;//每個葉子節點只能放入一個人 40 } 41 for(i=k-1;i>0;i--) 42 { 43 b[i].l=b[2*i].l; 44 b[i].r=b[2*i+1].r; 45 b[i].n=b[2*i].n+b[2*i+1].n;//每個區間是其左右子樹所能放入的人數總和 46 } 47 } 48 49 void insert(int i,int x,int m) 50 { 51 if(b[i].l==b[i].r)//找到葉子節點,這個節點存放該人,並且葉子節點能放入的人數清0 52 { 53 ans[b[i].l]=m; 54 b[i].n=0; 55 return; 56 } 57 if(x<=b[2*i].n)//其插入的位置若能放入左子樹(還能放人),往左子樹放人,否則走右子樹 58 insert(2*i,x,m); 59 else 60 insert(2*i+1,x-b[2*i].n,m); 61 b[i].n--; 62 } 63 64 int main() 65 { 66 int i,j; 67 while(scanf("%d",&n)!=EOF) 68 { 69 for(i=1;i<=n;i++) 70 scanf("%d%d",&a[i].n,&a[i].val); 71 init(); 72 for(i=n;i>0;i--)//逆推 73 { 74 insert(1,a[i].n+1,a[i].val); 75 } 76 cout<<ans[1]; 77 for(i=2;i<=n;i++) 78 cout<<" "<<ans[i]; 79 cout<<endl; 80 } 81 return 0; 82 }
POJ 2828 Buy Tickets(線段樹單點)