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 }
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 }
【題意】:就是給出一串數,當依次在將第一個數變爲最後一個數的過程當中,要你求它的最小逆序數。
【分析】:每次維護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 }
【題意】:有一塊長方形的廣告板,往上面貼廣告,而後給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 }
【題意】:給你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 }
【題意】:那個城市裏要競選市長,而後在一塊牆上能夠貼海報爲本身拉票,每一個人能夠貼連續的一塊區域,後來帖的能夠覆蓋前面的,問到最後一共能夠看到多少張海報。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 }
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 }
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 }
【題意】:算多個矩形的周長並
【分析】:《》
【代碼】:
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 }
【題意】:算多個矩形的面積並
【分析】:《》
【代碼】:
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 }