zoj 3635 線段樹 區間求位置 單點更新
阿新 • • 發佈:2019-02-20
/*
題意:輸入一個n,表示有 n 個空位,接下來就是 n 個數,第 i 個數 ai 表示第 i 個人要在坐在第 ai 個空位上;在輸入一個 m 表示有 m 次訪問,
每次訪問輸入一個整數 bi 表示第 bi 個人坐的位置標號。
分析:採用線段樹,線段樹裡存放的是這一段裡有多少個空位,從下往上更新,時間複雜度O(nlogn)。
*/
#include<iostream> #include<algorithm> #include<cstdio> #include<memory.h> using namespace std; #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r const int maxn=50002; int sum[maxn<<2],pos[maxn<<2]; void pushUP(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } //void pushDOWN(int rt) void build(int rt,int l,int r) { if(l==r) { sum[rt]=1; return; } int mid=(l+r)>>1; build(lson); build(rson); pushUP(rt); } void updata(int rt,int l,int r,int ans,int num,int idx) { if(l==r) { sum[rt]=0; pos[idx]=l; /// pushUP(rt); return; } int mid=(l+r)>>1; if(sum[rt<<1]+ans<num) updata(rson,ans+sum[rt<<1],num,idx); else updata(lson,ans,num,idx); pushUP(rt); } int main() { int i,j,n,m,bi,idx; while(scanf("%d",&n)!=EOF) { memset(sum,0,sizeof(sum)); memset(pos,0,sizeof(pos)); build(1,1,n); for(i=1; i<=n; i++) { scanf("%d",&bi); updata(1,1,n,0,bi,i); } scanf("%d",&m); if(m>=1) { scanf("%d",&idx); printf("%d",pos[idx]); } for(i=2; i<=m; i++) { scanf("%d",&idx); printf(" %d",pos[idx]); } printf("\n"); } return 0; }