1. 程式人生 > >hdu 2871 Memory Control (區間合並 連續段的起始位置 點所屬段的左右端點)

hdu 2871 Memory Control (區間合並 連續段的起始位置 點所屬段的左右端點)

位置 線段 初始 const pac %s names rebuild 大小

鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2871

題意:

四種操作:

1.Reset 清空所有內存
2.New x 分配一個大小為x的內存塊返回,返回能分配的最小的起始點

3.Free x 釋放當前點所在的內存塊,並輸出左右端點

4.Get x 返回第x個內存塊的起始點

討論每個操作的寫法:

第一個操作,把線段樹初始化就好了

第二個操作,區間合並的基礎操作,

第三個操作:多維護兩個數組:st,ed代表當前點所屬內存塊的左右區間

第四個操作:再開棵樹,存每個內存塊的起始點,每個起始點下標+1,然後直接找第k大就好了。註意每次2,3,操作內存塊發生變化時記得更新這個樹上的信息。

題面說了每組數據中間要有空行,不然會PE.

實現代碼:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ls rt<<1
#define rs rt<<1|1
const int M = 1e5 + 10;
int lsum[M<<2],rsum[M<<2
],sum[M<<2],lazy[M<<2],st[M<<2],ed[M<<2]; int cnt[M<<2],cov[M<<2],n; void pushup(int l,int r,int rt){ mid; lsum[rt] = lsum[ls]; rsum[rt] = rsum[rs]; sum[rt] = max(sum[ls],sum[rs]); if(lsum[rt] == m-l+1) lsum[rt] += lsum[rs]; if(rsum[rt] == r-m) rsum[rt] += rsum[ls]; sum[rt]
= max(rsum[ls]+lsum[rs],sum[rt]); } void pushdown(int l,int r,int rt){ if(lazy[rt]!=-1){ mid; lazy[ls] = lazy[rs] = lazy[rt]; sum[ls] = lsum[ls] = rsum[ls] = (m-l+1)*lazy[rt]; sum[rs] = lsum[rs] = rsum[rs] = (r-m)*lazy[rt]; st[ls] = st[rs] = st[rt]; ed[ls] = ed[rs] = ed[rt]; lazy[rt] = -1; } } void update(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ lazy[rt] = c; lsum[rt] = rsum[rt] = sum[rt] = (r-l+1)*c; if(c) st[rt] = ed[rt] = -1; else{ st[rt] = L; ed[rt] = R; } return ; } pushdown(l,r,rt); mid; if(L <= m) update(L,R,c,lson); if(R > m) update(L,R,c,rson); pushup(l,r,rt); } void rebuild(){ update(1,n,1,1,n,1); //cout<<sum[1]<<endl; cnt[1] = 0; cov[1] = 1; } int New(int p,int l,int r,int rt){ //返回空位的左邊界 if(l == r) return l; mid; pushdown(l,r,rt); if(sum[ls] >= p) return New(p,lson); else if(rsum[ls]+lsum[rs]>=p) return m-rsum[ls]+1; else return New(p,rson); } int Free(int p,int l,int r,int rt){ if(l == r) return rt; mid; pushdown(l,r,rt); if(p <= m) return Free(p,lson); else return Free(p,rson); } void up(int rt){ cnt[rt] = cnt[ls] + cnt[rs]; } void down(int rt){ if(cov[rt]){ cnt[ls] = cnt[rs] = 0; cov[ls] = cov[rs] = 1; cov[rt] = 0; } } int get(int p,int l,int r,int rt){ if(l == r) return l; mid; down(rt); if(cnt[ls] >= p) return get(p,lson); else return get(p-cnt[ls],rson); } void change(int p,int c,int l,int r,int rt){ if(l == r){ cnt[rt] = c; return; } down(rt); mid; if(p <= m) change(p,c,lson); else change(p,c,rson); up(rt); } int main() { int q,k,x; while(scanf("%d%d",&n,&q)!=EOF){ rebuild(); while(q--){ char op[20]; scanf("%s",op); if(op[0] == N){ scanf("%d",&x); //cout<<sum[1]<<" "<<x<<endl; if(sum[1] < x) printf("Reject New\n"); else{ int k = New(x,1,n,1); printf("New at %d\n",k); change(k,1,1,n,1); update(k,k+x-1,0,1,n,1); } } else if(op[0]==F){ scanf("%d",&x); int k = Free(x,1,n,1); if(st[k] < 0) printf("Reject Free\n"); else{ printf("Free from %d to %d\n",st[k],ed[k]); change(st[k],0,1,n,1); update(st[k],ed[k],1,1,n,1); } } else if(op[0] == R){ rebuild(); printf("Reset Now\n"); } else{ scanf("%d",&x); if(x > cnt[1]) printf("Reject Get\n"); else printf("Get at %d\n",get(x,1,n,1)); } } printf("\n"); } return 0; }

hdu 2871 Memory Control (區間合並 連續段的起始位置 點所屬段的左右端點)