POJ 2828 Buy Tickets | 線段樹的喵用
阿新 • • 發佈:2017-11-20
ans define 發現 維護 fine build poj print n)
題意:
給你n次插隊操作,每次兩個數,pos,w,意為在pos後插入一個權值為w的數;
最後輸出1~n的權值
題解:
首先可以發現,最後一次插入的位置是準確的位置
所以這個就變成了若幹個子問題,
所以用線段樹維護一下每個區間剩余多少位置可選
對於一個pos
如果左兒子的剩余超過當前位置,就遞歸進左子樹
反之就相當於留出了左兒子剩余的位置,遞歸進右子樹,當前位置變成pos-左兒子剩余位置
請註意是在後面插入
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 typedef longlong ll; 5 #define N 200010 6 using namespace std; 7 struct node 8 { 9 ll l,r,sum,w; 10 }t[4*N]; 11 ll p[N],w[N]; 12 ll read() 13 { 14 ll ret=0,neg=1; 15 char j=getchar(); 16 for (;j>‘9‘ || j<‘0‘;j=getchar()) 17 if (j==‘-‘) neg=-1; 18 for (;j<=‘9‘ && j>=‘0‘;j=getchar())19 ret=ret*10+j-‘0‘; 20 return ret*neg; 21 } 22 ll n,q,l,r,k,ans[N]; 23 void pushup(ll p) 24 { 25 t[p].sum=t[2*p].sum+t[2*p+1].sum; 26 } 27 void build(ll p,ll l,ll r) 28 { 29 t[p].l=l,t[p].r=r; 30 if (l!=r) 31 { 32 ll mid=l+r>>1; 33 build(2*p,l,mid); 34 build(2*p+1,mid+1,r); 35 pushup(p); 36 } 37 else 38 t[p].sum=1; 39 } 40 void modify(ll p,ll pos,ll k) 41 { 42 if (t[p].l==t[p].r) 43 { 44 ans[t[p].l]=k; 45 t[p].sum--; 46 return ; 47 } 48 if (t[2*p].sum>=pos) modify(2*p,pos,k); 49 else modify(2*p+1,pos-t[2*p].sum,k); 50 pushup(p); 51 } 52 int main() 53 { 54 while (scanf("%lld",&n)!=EOF) 55 { 56 build(1,1,n); 57 for (int i=1;i<=n;i++) 58 p[i]=read(),w[i]=read(); 59 for (int i=n;i>=1;i--) 60 modify(1,p[i]+1,w[i]); 61 for (int i=1;i<=n;i++) 62 printf("%lld%c",ans[i]," \n"[i==n]); 63 } 64 return 0; 65 }
POJ 2828 Buy Tickets | 線段樹的喵用