2014 summer 知識點總結1之線段樹

HDU 1166ios

【題意】:ide

n個陣營一字排開,每一個初始有a[i]我的。現有兩種操做:ui

Q a b 查詢[a,b]之間總人數並輸出spa

A/S a b 在a號位添加/刪除b我的code

【分析】:最基本的單點更新和區間查詢,維護節點信息sum[o]blog

【代碼】:get

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 
 5 using namespace std;
 6 
 7 int numv[50005<<2];
 8 int A[50005];
 9 
10 void builtTree(int o,int l,int r){
11     if(l==r) {
12         numv[o]=A[l];
13         return ;
14     }
15     int m=l+(r-l)/2;
16     builtTree(2*o,l,m);
17     builtTree(2*o+1,m+1,r);
18     numv[o]=numv[2*o]+numv[2*o+1];
19     return ;
20 }
21 void Update(int o,int l,int r,int p,int x){
22     if(l==r && l==p){
23         A[l]=x;
24         numv[o]=x;
25         return ;
26     }
27     int m=l+(r-l)/2;
28     if (p<=m) Update(2*o,l,m,p,x);
29     if (p>=m+1)Update(2*o+1,m+1,r,p,x);
30     numv[o]=numv[2*o]+numv[2*o+1];
31 }
32 int Query(int ql,int qr,int o,int l,int r){
33     if (ql<=l && r<=qr) return numv[o];
34     int m=l+(r-l)/2;
35     int ans=0;
36     if (ql<=m) ans+=Query(ql,qr,2*o,l,m);
37     if (m+1<=qr) ans+=Query(ql,qr,2*o+1,m+1,r);
38     return ans;
39 }
40 int t,n;
41 int main(){
42     scanf("%d",&t);
43     for(int cas=1;cas<=t;cas++){
44         scanf("%d",&n);
45         printf("Case %d:\n",cas);
46         for(int i=1;i<=n;i++) scanf("%d",&A[i]);
47         builtTree(1,1,n);
48         char s[105];
49         while(~scanf("%s",s)){
50             if (s[0]=='E') {
51                 break;
52             }
53             int a,b;
54             scanf("%d%d",&a,&b);
55             if (s[0]=='Q'){
56                 int ans=Query(a,b,1,1,n);
57                 printf("%d\n",ans);
58             }
59             if (s[0]=='A'){
60                 Update(1,1,n,a,A[a]+b);
61             }
62             if (s[0]=='S'){
63                 Update(1,1,n,a,A[a]-b);
64             }
65         }
66     }
67     return 0;
68 }
View Code

 

HDU 1754string

【題意】:給n個數字。m次操做,每次操做更新一個數字或者查詢區間最大值。hash

【分析】:基本單點更新區間查詢,維護節點信息max[o]it

【代碼】:

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #define Mod 1000000007
 5 #define LL long long
 6 #define toL 2*o,l,m
 7 #define toR 2*o+1,m+1,r
 8 using namespace std;
 9 
10 int maxv[200005<<2];
11 int A[200005];
12 
13 void builtTree(int o,int l,int r){
14     if (l==r){
15         maxv[o]=A[l];
16         return ;
17     }
18     int m=(l+r)/2;
19     builtTree(toL);
20     builtTree(toR);
21     maxv[o]=max(maxv[2*o],maxv[2*o+1]);
22     return ;
23 }
24 void Updata(int o,int l,int r,int p,int x){
25     if (l==r && p==l){
26         maxv[o]=x;
27         return ;
28     }else {
29         int m=(r+l)/2;
30         if (p<=m) Updata(toL,p,x);
31         if (m+1<=p) Updata(toR,p,x);
32         maxv[o]=max(maxv[2*o],maxv[2*o+1]);
33         return ;
34     }
35 }
36 int Query(int o,int l,int r,int ql,int qr){
37     if (ql<=l && r<=qr) return maxv[o];
38     int m=(r+l)/2;
39     int ans=-1;
40     if (ql<=m) ans=max(ans,Query(toL,ql,qr));
41     if (m+1<=qr) ans=max(ans,Query(toR,ql,qr));
42     return ans;
43 }
44 int n,q;
45 
46 int main(){
47     while(~scanf("%d%d",&n,&q)){
48         for(int i=1;i<=n;i++) scanf("%d",&A[i]);
49         builtTree(1,1,n);
50         for(int i=1;i<=q;i++){
51             int a,b;
52             char s[3];
53             scanf("%s%d%d",s,&a,&b);
54             if (s[0]=='Q'){
55                 printf("%d\n",Query(1,1,n,a,b));
56             }
57             if (s[0]=='U'){
58                 Updata(1,1,n,a,b);
59             }
60         }
61     }
62     return 0;
63 }
View Code

 

HDU 1394

【題意】:就是給出一串數,當依次在將第一個數變爲最後一個數的過程當中,要你求它的最小逆序數。

【分析】:每次維護sumv求區間內有多少個數字,處理出LOW[],UP[]後利用sum每次枚舉

 for(int i=1;i<=n;i++){ scanf("%d",&A[i]); A[i]++; // cout<<"Q="<<Query(1,1,n,A[i]+1,n)<<endl; if (A[i]+1<=n) sum+=Query(1,1,n,A[i]+1,n); updata(1,1,n,A[i],1);//令A【i】的位置爲1,那麼sunv就至關於一個求和了 A[i]--;//信息已經保存到樹中,A[i]可還原 }

【代碼】:

 1 /*HDU1394搜索寫法*/
 2 #include <iostream>
 3 #include <string.h>
 4 #include <stdio.h>
 5 #define LL 2*o,l,m
 6 #define LR 2*o+1,m+1,r
 7 using namespace std;
 8 
 9 int A[50005];
10 int Low[50005],Up[50005];
11 int numv[50005<<2];//[1...50005]有多少個數
12 
13 int Query(int o,int l,int r,int ql,int qr){
14     if (ql<=l && r<=qr) return numv[o];
15     int m=(r+l)>>1;
16     int ans=0;
17     if (ql<=m) ans+=Query(LL,ql,qr);
18     if (m+1<=qr) ans+=Query(LR,ql,qr);
19     return ans;
20 }
21 void updata(int o,int l,int r,int p,int x){
22    // cout<<"l="<<l<<","<<"r="<<r<<endl;
23 
24     if (l==r && p==l) {
25         numv[o]=1;
26         return ;
27     }
28     int m=(r+l)>>1;
29     if (p<=m)updata(LL,p,x);
30     if (m+1<=p)updata(LR,p,x);
31     numv[o]=numv[2*o]+numv[2*o+1];
32     return;
33 }
34 int main(){
35     int n;
36     while(~scanf("%d",&n)){
37         memset(numv,0,sizeof(numv));
38         int ans,sum=0;
39         for(int i=1;i<=n;i++){
40             scanf("%d",&A[i]);
41             A[i]++;
42         //    cout<<"Q="<<Query(1,1,n,A[i]+1,n)<<endl;
43             if (A[i]+1<=n) sum+=Query(1,1,n,A[i]+1,n);
44             updata(1,1,n,A[i],1);//令A【i】的位置爲1,那麼sunv就至關於一個求和了
45             A[i]--;//信息已經保存到樹中,A[i]可還原
46         }
47         ans=sum;
48         for(int i=0;i<n;i++){
49             Low[i]=i;
50             Up[i]=n-i-1;
51         }
52         for(int i=1;i<=n-1;i++){
53             sum=sum+(Up[A[i]]-Low[A[i]]);
54             ans=min(sum,ans);
55         }
56         printf("%d\n",ans);
57     }
58     return 0;
59 }
View Code

 

 HDU 2795

【題意】:有一塊長方形的廣告板,往上面貼廣告,而後給n個1*wi的廣告,要求把廣告貼上去,若是前面的行能夠貼,就要貼前面的而且要靠左貼,前面的貼不下就貼在下面,廣告的高度是wi,若是能貼在上面輸出最小的高度,若是不能就輸出-1。

【分析】:以h爲軸創建線段樹,每次維護區間內剩餘A[i]的最大值max[o],假設咱們要新增的廣告的長度爲L

那麼,當max[o]<L的時候確定已經不能放置,由於每次挨着左邊的放,因此每次剩餘的A[i]=A[i]-L便可

【代碼】:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 #define Lson l,m,2*o
 7 #define Rson m+1,r,2*o+1
 8 using namespace std;
 9 int maxv[200100<<2];
10 void updata(int l,int r,int o,int p,int x){
11     if (l==r){
12         maxv[o]=x;
13         return ;
14     }else {
15         int m=(l+r)>>1;
16         if (p<=m)updata(Lson,p,x);
17         else updata(Rson,p,x);
18         maxv[o]=max(maxv[2*o],maxv[2*o+1]);
19     }
20     return ;
21 }
22 int h,w,n;
23 void builtTree(int l,int r,int o){
24     if (l==r) {
25         maxv[o]=w;
26         return ;
27     }
28     int m=(r+l)>>1;
29     builtTree(Lson);
30     builtTree(Rson);
31     maxv[o]=max(maxv[2*o],maxv[2*o+1]);
32     return ;
33 }
34 int Query(int l,int r,int o,int x){
35     if (l==r){
36         updata(1,h,1,l,maxv[o]-x);
37         return l;
38     }else {
39         int m=(r+l)>>1;
40         if (maxv[2*o]>=x) return Query(Lson,x);
41         else return Query(Rson,x);
42     }
43 }
44 int main(){
45     while(~scanf("%d%d%d",&h,&w,&n)){
46         if (h>n) h=n;
47         builtTree(1,h,1);
48         while(n--){
49             int x;
50             scanf("%d",&x);
51             if (maxv[1]<x)//沒有任何地方能夠放
52             {
53                 puts("-1");
54             }else {
55                 printf("%d\n",Query(1,h,1,x));
56             }
57         }
58     }
59     return 0;
60 }
View Code

 

POJ 3468

【題意】:給你N個數,Q個操做,操做有兩種,‘Q a b ’是詢問a~b這段數的和,‘C a b c’是把a~b這段數都加上c。

【分析】:成段更新,每次給區間的每一個元素加上C,那麼當用到下層節點的時候,再把標記下傳,更新區間便可,標記是這個區間的每一個數要增長的C值,

當一段被重複覆蓋時,更新C便可,當標記下傳後,這段區間的sum已經增長過了len*C,那麼區間對應的標記減去C便可。區間標記的C爲0時,表示更新完畢了。

【代碼】:

 1 /*poj3468
 2 */
 3 #include<iostream>
 4 #include<stdio.h>
 5 #include<string.h>
 6 #include<algorithm>
 7 #include<stdlib.h>
 8 #define Lson l,m,2*o
 9 #define Rson m+1,r,2*o+1
10 #define LL long long
11 using namespace std;
12 
13 LL sum[100010<<2];
14 LL add[100010<<2];
15 LL A[100010];
16 void PushDown(int o,int len){
17     if (add[o]){
18         add[2*o]+=add[o];
19         add[2*o+1]+=add[o];
20         sum[2*o]+=add[o]*(len-(len>>1));
21         sum[2*o+1]+=add[o]*(len>>1);
22         add[o]=0;
23     }
24     return ;
25 }
26 void PushUp(int o){
27     sum[o]=sum[2*o]+sum[2*o+1];
28 }
29 void builtTree(int l,int r,int o){
30     add[o]=0;
31     if (l==r){
32         sum[o]=A[l];
33     }else {
34         int m=(l+r)>>1;
35         builtTree(Lson);
36         builtTree(Rson);
37         PushUp(o);
38     }
39     return ;
40 }
41 LL Query(int l,int r,int o,int L,int R){
42     if (L<=l && r<=R){
43         return sum[o];
44     }
45     PushDown(o,r-l+1);
46     int m=(l+r)>>1;
47     LL ans=0;
48     if (L<=m) ans+=Query(Lson,L,R);
49     if (m+1<=R) ans+=Query(Rson,L,R);
50     return ans;
51 }
52 void Updata(int l,int r,int o,int L,int R,int x){
53     if (L<=l && r<=R){
54         sum[o]+=(LL)(r-l+1)*(LL)x;
55         add[o]+=x;
56         return ;
57     }
58     PushDown(o,r-l+1);
59     int m=(r+l)>>1;
60     if (L<=m) Updata(Lson,L,R,x);
61     if (m+1<=R) Updata(Rson,L,R,x);
62     PushUp(o);
63     return ;
64 }
65 int N,Q;
66 int main(){
67 ////    freopen("out.txt","w",stdout);
68     while(~scanf("%d%d",&N,&Q)){
69         for(int i=1;i<=N;i++) scanf("%lld",&A[i]);
70         builtTree(1,N,1);
71         char s[10];
72         while(Q--){
73             scanf("%s",s);
74             int l,r,x;
75             if (s[0]=='Q'){
76                 scanf("%d%d",&l,&r);
77                 printf("%lld\n",Query(1,N,1,l,r));
78             }
79             if (s[0]=='C'){
80                 scanf("%d%d%d",&l,&r,&x);
81                 Updata(1,N,1,l,r,x);
82             }
83         }
84     }
85     return 0;
86 }
View Code

 

POJ 2528

【題意】:那個城市裏要競選市長,而後在一塊牆上能夠貼海報爲本身拉票,每一個人能夠貼連續的一塊區域,後來帖的能夠覆蓋前面的,問到最後一共能夠看到多少張海報。1 <= n <= 10000 ,1 <= i <= n, 1 <= li <= ri <= 10000000 .

【分析】:首先看這個N的範圍,基本上是和區間有關的操做。

若是把新增一張海報 I 當作把一個區間的數字都變成 I+1,咱們想要的是一段區間裏不一樣的數字的個數num[o]。

顯然,咱們不可能把一個區間的數字都更新完了再花O(R-L)的時間更新這個值num[o]。

那麼怎麼辦呢?咱們向區間的合併上考慮。

【代碼】:具體的分析看代碼註釋:

/*解題的重點:
一、區間更新成一個數,用lazy標記
二、左邊的範圍很大,用離散化
三、離散化處理,二分查找出x的對應序號
四、查詢,對於col[o]>0的區間說明,這個區間都是col[o],直接ans+1返回便可
可是由於計算的是露出的海報的總的種數,因此查找過的點不須要再計算。
也能保證單點的col[o]大於0,由於col標記不須要下傳
五、可是題目略有歧義,這個更新的(l,r)是否是座標軸上的點呢?
是的話,要處理成(l,r-1)。
*/

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 #include<map>
 7 #define Lson l,m,2*o
 8 #define Rson m+1,r,2*o+1
 9 #define LL long long
10 using namespace std;
11 
12 int lx[41111];
13 int rx[41111];
14 int px[41111<<1];
15 int col[41111<<3];
16 bool vis[41111<<1];
17 
18 /*解題的重點:
19 一、區間更新成一個數,用lazy標記
20 二、左邊的範圍很大,用離散化
21 三、離散化處理,二分查找出x的對應序號
22 四、查詢,對於col[o]>0的區間說明,這個區間都是col[o],直接ans+1返回便可
23 可是由於計算的是露出的海報的總的種數,因此查找過的點不須要再計算。
24 也能保證單點的col[o]大於0,由於col標記不須要下傳
25 五、可是題目略有歧義,這個更新的(l,r)是否是座標軸上的點呢?
26 是的話,要處理成(l,r-1)。
27 */
28 int T,N,cnt,ans;
29 int binary(int n,int x){//px[0]--px[n-1]中找到x
30     int ans;
31     ans=lower_bound(px,px+n,x)-px;
32     return ans+1;
33 }
34 void PushDown(int o){
35     if (col[o]){
36         col[2*o]=col[o];
37         col[2*o+1]=col[o];
38         col[o]=0;
39     }
40     return;
41 }
42 
43 void Query(int l,int r,int o){//
44     if (col[o]){//以區間代替點
45         if (!vis[col[o]]){//沒必要查找到每個點,區間代替下面的每一個單點便可
46             ans++;
47             vis[col[o]]=true;
48         }
49         return ;
50     }
51     if (l==r) return ;//單點保證在上面處理過了
52     int m=(l+r)>>1;
53     Query(Lson);
54     Query(Rson);
55 }
56 void Updata(int l,int r,int o,int L,int R,int x){
57     if (L<=l&&r<=R){//給找到的區間加懶惰標記
58         col[o]=x;
59         return ;
60     }
61     PushDown(o);//如果要向下層更新,那麼懶惰標記要下傳
62     int m=(l+r)>>1;
63     if (L<=m) Updata(Lson,L,R,x); //繼續向下搜索更新
64     if (m+1<=R) Updata(Rson,L,R,x);
65     return ;
66 }
67 int main(){
68     scanf("%d",&T);
69     while(T--){
70         scanf("%d",&N);
71         cnt=0;
72         for(int i=0;i<N;i++){//離散化
73             scanf("%d",&lx[i]);
74             scanf("%d",&rx[i]);
75             px[cnt++]=lx[i];
76             px[cnt++]=rx[i];
77         }
78         sort(px,px+cnt);
79         int cnt2=0;
80         px[cnt]=-1;
81         for(int i=0;i<cnt;i++){
82             if (px[i]!=px[i+1]) px[cnt2++]=px[i];//去重而且按順序統計離散的點
83         }
84         ans=0;
85         memset(vis,0,sizeof(vis));
86         memset(col,0,sizeof(col));
87         for(int i=0;i<N;i++){
88             int k1=binary(cnt2,lx[i]),k2=binary(cnt2,rx[i]);//二分查找到標號
89             Updata(1,cnt2,1,k1,k2,i+1);
90         }
91         Query(1,cnt2,1);
92         printf("%d\n",ans);
93 
94     }
95     return 0;
96 }
View Code

 

 

POJ 3667 (重難點)

【題意】:

有N個房間,M次操做。1 a表示找到連續的長度爲a的空房間,若是有多解,優先左邊的,即表示入住,輸出入住的人的最左邊的房間號。2 b len把起點爲b長度的len的房間清空,即退房。

【分析】:

假設:若是房間沒人,標記爲1,不然標記爲0

首先,咱們確定是想快速查找出一段區間內是否有知足的連續長度的0的存在,可是線段樹的區間已經固定好了。

可是有可能存在兩個區間合起來中間有長度爲L的連續空房間。

那麼咱們就要維護:

Lsum[o]:區間左邊連續的0的個數

Rsum[o]:區間右邊連續的0的個數

Msum[o]: 區間中最大的連續的0的個數

那麼當咱們查找區間o(保證Msum[o]>=Num)時,由於要儘可能的向左分配,因此若Msum[2*o]固然向左分配,若Rsum[2*o]+Lsum[2*o+1]>=Num,則直接能夠計算出入住的位置p= m-Rsum[2*o]+1;

int Query(int l,int r,int o,int D){//向左搜索
    int m=(r+l)>>1;
    if (l==r){//當且D==1時纔會有這個出口
        return l;
    }
    PushDown(o,r-l+1);
    if (max_sub[2*o]>=D){
        return Query(Lson,D);
    }else {
        if (max_suffix[2*o]+max_prefix[2*o+1]>=D){
            return m-max_suffix[2*o]+1;
        }
    }
    return Query(Rson,D);
}
區間更新:
一、有兩種:分別是一段區間更新爲1,或 0
二、Pushdown標記PushUp標記
三、關鍵是同時維護:sum[o]
    if (L<=l && r<=R){
        col[o]=x;
        max_sub[o]=max_suffix[o]=max_prefix[o]=(r-l+1)*x;
        return;
    }
四、區間合併,維護信息
void PushUp(int l,int r,int o){
    int m=(r+l)>>1;
    int l1=m-l+1,l2=r-(m+1)+1;
    max_sub[o]=max(max_sub[2*o],max_sub[2*o+1]);
    max_sub[o]=max(max_sub[o],max_suffix[2*o]+max_prefix[2*o+1]);
    if (max_prefix[2*o]==l1){
        max_prefix[o]=l1+max_prefix[2*o+1];//整個區間能夠合併
    }else max_prefix[o]=max_prefix[2*o];
    if (max_suffix[2*o+1]==l2){
        max_suffix[o]=l2+max_suffix[2*o];
    }else max_suffix[o]=max_suffix[2*o+1];
    return ;
}

【代碼】:

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #define maxn 51000
  5 #define Lson l,m,2*o
  6 #define Rson m+1,r,2*o+1
  7 using namespace std;
  8 int col[maxn<<2];
  9 int max_sub[maxn<<2];//連續的1的個數
 10 int max_prefix[maxn<<2];//靠左的連續的1的個數
 11 int max_suffix[maxn<<2];//靠右的連續的1的個數
 12 int N,M;
 13 void PushUp(int l,int r,int o){
 14     int m=(r+l)>>1;
 15     int l1=m-l+1,l2=r-(m+1)+1;
 16     max_sub[o]=max(max_sub[2*o],max_sub[2*o+1]);
 17     max_sub[o]=max(max_sub[o],max_suffix[2*o]+max_prefix[2*o+1]);
 18     if (max_prefix[2*o]==l1){
 19         max_prefix[o]=l1+max_prefix[2*o+1];//整個區間能夠合併
 20     }else max_prefix[o]=max_prefix[2*o];
 21     if (max_suffix[2*o+1]==l2){
 22         max_suffix[o]=l2+max_suffix[2*o];
 23     }else max_suffix[o]=max_suffix[2*o+1];
 24     return ;
 25 }
 26 //1表示房間空,0表示不可用
 27 void PushDown(int o,int len)//由於有區間上的清零,因此要PushDown
 28 {
 29     if (col[o]==-1) return;
 30     col[2*o]=col[o];
 31     col[2*o+1]=col[o];
 32     if (col[o]==1){
 33         max_sub[2*o]=max_suffix[2*o]=max_prefix[2*o]=(len-(len>>1));
 34         max_sub[2*o+1]=max_suffix[2*o+1]=max_prefix[2*o+1]=len>>1;
 35     }
 36     if (col[o]==0){
 37         max_sub[2*o]=max_suffix[2*o]=max_prefix[2*o]=0;
 38         max_sub[2*o+1]=max_suffix[2*o+1]=max_prefix[2*o+1]=0;
 39     }
 40     col[o]=-1;
 41 }
 42 void Updata(int l,int r,int o,int L,int R,int x){
 43     if (L<=l && r<=R){
 44         col[o]=x;
 45         max_sub[o]=max_suffix[o]=max_prefix[o]=(r-l+1)*x;
 46         return;
 47     }
 48     PushDown(o,r-l+1);
 49     int m=(l+r)>>1;
 50     if (L<=m) Updata(Lson,L,R,x);
 51     if (m+1<=R) Updata(Rson,L,R,x);
 52     PushUp(l,r,o);
 53     return;
 54 }
 55 int Query(int l,int r,int o,int D){//向左搜索
 56     int m=(r+l)>>1;
 57     if (l==r){//當且D==1時纔會有這個出口
 58         return l;
 59     }
 60     PushDown(o,r-l+1);
 61     if (max_sub[2*o]>=D){
 62         return Query(Lson,D);
 63     }else {
 64         if (max_suffix[2*o]+max_prefix[2*o+1]>=D){
 65             return m-max_suffix[2*o]+1;
 66         }
 67     }
 68     return Query(Rson,D);
 69 }
 70 
 71 void BuiltTree(int l,int r,int o){
 72     col[o]=-1;
 73     if (l==r){
 74         max_sub[o]=1;
 75         max_suffix[o]=1;
 76         max_prefix[o]=1;
 77         return ;
 78     }
 79     int m=(l+r)>>1;
 80     BuiltTree(Lson);
 81     BuiltTree(Rson);
 82     PushUp(l,r,o);
 83     return ;
 84 }
 85 int main(){
 86     while(~scanf("%d%d",&N,&M)){
 87         BuiltTree(1,N,1);
 88         int q,a,b;
 89         while(M--){
 90             scanf("%d",&q);
 91             if (q==1){
 92                 scanf("%d",&a);
 93                 if (max_sub[1]<a){
 94                     puts("0");
 95                 }else {
 96                     int k=Query(1,N,1,a);
 97                     printf("%d\n",k);
 98                     Updata(1,N,1,k,k+a-1,0);
 99                 }
100             }
101             if (q==2){
102                 scanf("%d%d",&a,&b);
103                 Updata(1,N,1,a,a+b-1,1);
104             }
105         }
106     }
107     return 0;
108 }
View Code

 

CodeForces 46D

題意】:

在長爲L的(點0~點L)的線段上停車開車操做;

停車 1 x:車長x,須要b+x+f的空餘才能使車停進去,多個區域,選擇最左邊

開車 2 x:第x次操做,停進的車,開出去

分析】:

和poj3667很類似,可是處理首位時要特判,同時記錄下來第x次操做的車的長度和插入的位置,作插入或更新便可

代碼】:

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #define maxn 110000
  5 #define Lson l,m,2*o
  6 #define Rson m+1,r,2*o+1
  7 #define LL long long
  8 using namespace std;
  9 int sum[maxn<<2];
 10 int lsum[maxn<<2];
 11 int rsum[maxn<<2];
 12 int col[maxn<<2];
 13 void PushUp(int o,int len){
 14     sum[o]=max(sum[2*o],sum[2*o+1]);
 15     sum[o]=max(sum[o],rsum[2*o]+lsum[2*o+1]);
 16     lsum[o]=lsum[2*o];
 17     if (lsum[2*o]==len-(len>>1)) lsum[o]+=lsum[2*o+1];
 18     rsum[o]=rsum[2*o+1];
 19     if (rsum[2*o+1]==len>>1) rsum[o]+=rsum[2*o];
 20     return;
 21 }
 22 void PushDown(int o,int len){
 23     if (col[o]==-1) return;//col==1,表示可使用
 24     col[2*o]=col[2*o+1]=col[o];
 25     sum[2*o]=lsum[2*o]=rsum[2*o]=(len-(len>>1))*col[o];
 26     sum[2*o+1]=rsum[2*o+1]=lsum[2*o+1]= (len>>1)*col[o];
 27     col[o]=-1;
 28     return;
 29 }
 30 void Updata(int l,int r,int o,int L,int R,int x){
 31     if (L<=l && r<=R){
 32         col[o]=x;
 33         sum[o]=lsum[o]=rsum[o]=(r-l+1)*x;
 34         return ;
 35     }
 36     PushDown(o,r-l+1);
 37     int m=(r+l)>>1;
 38     if (L<=m) Updata(Lson,L,R,x);
 39     if (m+1<=R) Updata(Rson,L,R,x);
 40     PushUp(o,r-l+1);
 41     return ;
 42 }
 43 int Query(int l,int r,int o,int D){
 44 //    cout<<"l="<<l<<","<<"r="<<r<<endl;
 45 //    cout<<"sum="<<sum[o]<<endl;
 46     if (l==r) return l;
 47     PushDown(o,r-l+1);
 48     int m=(l+r)>>1;
 49     if (sum[2*o]>=D) return Query(Lson,D);
 50     else {
 51         if (rsum[2*o]+lsum[2*o+1]>=D){
 52             return m-rsum[2*o]+1;
 53         }
 54         return Query(Rson,D);
 55     }
 56 }
 57 void BuiltTree(int l,int r,int o){
 58     col[o]=-1;
 59     if (l==r){
 60         sum[o]=lsum[o]=rsum[o]=1;
 61         return ;
 62     }
 63     int m=(l+r)>>1;
 64     BuiltTree(Lson);
 65     BuiltTree(Rson);
 66     PushUp(o,r-l+1);
 67     return ;
 68 }
 69 int L,b,f;
 70 int px[110];
 71 int py[110];
 72 int main(){
 73 //    freopen("out.txt","w",stdout);
 74     while(~scanf("%d%d%d",&L,&b,&f)){
 75         int n;
 76         scanf("%d",&n);
 77         BuiltTree(1,L+b+f,1);
 78         for(int i=0;i<n;i++){
 79             int q,a;
 80             scanf("%d%d",&q,&a);
 81             if (q==1){
 82 //                cout<<"sum[1]:"<<sum[1]<<endl;
 83                 if (sum[1]<a+b+f){
 84                     puts("-1");
 85                     continue;
 86                 }
 87                 int p=Query(1,L+b+f,1,a+b+f);
 88 
 89                 p=p+b;
 90                 printf("%d\n",p-b-1);
 91 
 92 //            cout<<"p="<<p<<endl;
 93                 px[i]=p;py[i]=p+a-1;
 94 //                cout<<"px="<<px[i]<<","<<"py="<<py[i]<<endl;
 95                 Updata(1,L+b+f,1,px[i],py[i],0);
 96             }
 97             if (q==2){
 98                 Updata(1,L+b+f,1,px[a-1],py[a-1],1);
 99             }
100         }
101     }
102     return 0;
103 }
View Code

 

HDU 2795

題意】:算多個矩形的周長並

分析】:《》

代碼】:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 #define Lson l,m,2*o
 7 #define Rson m+1,r,2*o+1
 8 using namespace std;
 9 int maxv[200100<<2];
10 void updata(int l,int r,int o,int p,int x){
11     if (l==r){
12         maxv[o]=x;
13         return ;
14     }else {
15         int m=(l+r)>>1;
16         if (p<=m)updata(Lson,p,x);
17         else updata(Rson,p,x);
18         maxv[o]=max(maxv[2*o],maxv[2*o+1]);
19     }
20     return ;
21 }
22 int h,w,n;
23 void builtTree(int l,int r,int o){
24     if (l==r) {
25         maxv[o]=w;
26         return ;
27     }
28     int m=(r+l)>>1;
29     builtTree(Lson);
30     builtTree(Rson);
31     maxv[o]=max(maxv[2*o],maxv[2*o+1]);
32     return ;
33 }
34 int Query(int l,int r,int o,int x){
35     if (l==r){
36         updata(1,h,1,l,maxv[o]-x);
37         return l;
38     }else {
39         int m=(r+l)>>1;
40         if (maxv[2*o]>=x) return Query(Lson,x);
41         else return Query(Rson,x);
42     }
43 }
44 int main(){
45     while(~scanf("%d%d%d",&h,&w,&n)){
46         if (h>n) h=n;
47         builtTree(1,h,1);
48         while(n--){
49             int x;
50             scanf("%d",&x);
51             if (maxv[1]<x)//沒有任何地方能夠放
52             {
53                 puts("-1");
54             }else {
55                 printf("%d\n",Query(1,h,1,x));
56             }
57         }
58     }
59     return 0;
60 }
View Code

 

HDU 1542

題意】:算多個矩形的面積並

分析】:《》

代碼】:

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <algorithm>
 5 #define Lson l,m,2*o
 6 #define Rson m+1,r,2*o+1
 7 
 8 using namespace std;
 9 double Y[255];//hash映射
10 double len[255<<2];
11 int add[255<<2];
12 int n,cas=0,cnt1,cnt2;
13 int binary(double key){
14     int l=0,r=cnt1-1;
15     while(l<r){
16         int m=(l+r)>>1;
17         if (Y[m]==key) return m;
18         if (Y[m]<key) l=m+1;
19         if (Y[m]>key) r=m;
20     }
21     return l;
22 }
23 void PushUp(int o,int l,int r){
24     if (add[o]>0){
25         len[o]=Y[r+1]-Y[l];
26     }else {
27         if (l==r) len[o]=0;
28         else {
29             len[o]=len[o*2]+len[2*o+1];
30         }
31     }
32     return ;
33 }
34 void Updata(int l,int r,int o,int L,int R,int c){
35     if (L<=l && r<=R){
36         add[o]+=c;
37         PushUp(o,l,r);
38         return ;
39     }
40     int m=(r+l)>>1;
41     if (L<=m) Updata(Lson,L,R,c);
42     if (m+1<=R) Updata(Rson,L,R,c);
43     PushUp(o,l,r);
44     return ;
45 }
46 struct Line {
47     double p;
48     double _d,_u;
49     int c;
50     bool operator<(const Line&X)const{
51         if (p==X.p) return c>X.c;
52         else return p<X.p;
53     }
54 }Lines[255];
55 int main(){
56     while(~scanf("%d",&n)&&n){
57         cas++;
58         cnt1=cnt2=0;
59         for(int i=0;i<n;i++){
60             double x1,y1,x2,y2;
61             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
62             Y[cnt1++]=y1;Y[cnt1++]=y2;
63             Lines[cnt2++]=(Line){x1,y1,y2,1};
64             Lines[cnt2++]=(Line){x2,y1,y2,-1};
65         }
66         sort(Y,Y+cnt1);//創建i到Y的映射
67         sort(Lines,Lines+cnt2);
68 
69         double ans=0;
70         for(int i=0;i<cnt2;i++){
71             int k1=binary(Lines[i]._d),k2=binary(Lines[i]._u);
72             Updata(0,cnt1,1,k1,k2-1,Lines[i].c);
73             ans+=len[1]*(Lines[i+1].p-Lines[i].p);
74         }
75         printf("Test case #%d\n",cas);
76         printf("Total explored area: %.2lf\n\n",ans);
77     }
78     return 0;
79 }
View Code
相關文章
相關標籤/搜索