Buy Tickets
阿新 • • 發佈:2019-01-07
/*題意:有n個人,給出n個人要插入的位置與其價值,輸出最後的價值*/ /*【題解】: 線段樹節點中儲存這一段中的空位數,然後倒序對pos插入: 例如: 0 77 1 51 1 33 2 69 先取: 2 69 —— —— —69— —— (需要前面有3個空位才能插入) 然後取: 1 33 —— —33— —69— —— (需要前面有2個空位才能插入) 然後取: 1 51 —— —33— —69— —51— (需要前面有2個空位才能插入) 前面只有1個空位 故插入後面空格 然後取: 0 77 —77— —33— —69— —51— (需要前面有1個空位才能插入) */ /*由於左後一個人插進來後他的位置肯定是固定的 我們就可以倒著來插,最後一個固定後,如果倒數第二個插入的序號小於當前那麼就往前插到序號上,否則往後插,往後的話序號需要減去當前這個數左邊的空位數 因為左右都是從0位置開始標記的 因此結構體裡需要維持節點左右邊的空位個數,當前插隊序號小於左邊空位插左邊,大於的話插右邊,但是需要需要減去左邊空位。。因為右邊也是從0位置開始算起的,並且 我們是倒著插,所以空位個數才是當時的需要插的位置,已經被佔的位置當時還不存在..*/ #include<stdio.h> #include<iostream> #include<algorithm> using namespace std; struct node { int l, r, sum; int mark; }dp[1000005]; int p[200005]; int v[200005]; int ans[200005]; void Create(int l, int r, int i) { dp[i].l = l; dp[i].r = r; dp[i].sum = (r - l + 1); if (l == r) { return; } int mid = (l + r) >> 1; Create(l, mid, i * 2); Create(mid + 1, r, i * 2 + 1); } void Change(int a, int b, int i)//a表示空格數量,b為輸入的值,i為節點 { if (dp[i].l == dp[i].r) { dp[i].sum = 0; ans[dp[i].l] = b; return; } int mid = (dp[i].l + dp[i].r) / 2; //優先放在左邊 if (a <= dp[i * 2].sum)//如果左邊放的下 { Change(a, b, i * 2); } else//左邊放不下 Change(a - dp[i * 2].sum, b, i * 2 + 1); dp[i].sum = dp[i * 2].sum + dp[i * 2 + 1].sum; } int main() { int n; while (cin>>n) { Create(1, n, 1); for (int i = 0; i < n; i++) { scanf("%d%d", &p[i], &v[i]); } for (int i = n - 1; i >= 0; i--) { Change(p[i] + 1, v[i], 1); } for (int i = 1; i <= n; i++) { if (i != 1) { cout << " "; } cout << ans[i]; } cout << endl; } return 0; }