学习了自底向上的非递归线段树,深感精妙!!
大牛的博客:http://blog.csdn.net/zearot/article/details/48299459
张坤玮---统计的力量
The Union of k-Segments
题意:求被覆盖k次及以上的点或者线段。
看到别人直接用扫描线写的,更方便一些。
不过拿来练习线段树也不错。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1000010; 4 int cn,c[maxn<<1]; //离散化 5 int n,k,l[maxn],r[maxn]; 6 void discrete(){ 7 sort(c+1,c+1+cn); 8 int I=1; 9 for(int i=2;i<=cn;i++) if(c[i]!=c[i-1]) c[++I]=c[i]; 10 cn=I; 11 } 12 int getid(int x){ 13 int L=1,R=cn,m; 14 while(L<=R){ 15 m=(L+R)>>1; 16 if(c[m]==x) return m; 17 if(c[m]<x) L=m+1; 18 else R=m-1; 19 } 20 } 21 int N; 22 int add[maxn<<3],p[maxn<<3]; 23 void build(int n){ 24 N=1;while(N<n+2) N<<=1; 25 memset(add,0,sizeof(add)); 26 memset(p,0,sizeof(p)); 27 } 28 void update(int L,int R){ 29 for(int s=N+L-1,t=N+R;s^t^1;s>>=1,t>>=1){ 30 if(~s&1) ++add[s^1]; 31 if( t&1) ++add[t^1]; 32 } 33 for(int s=N+L-1,t=N+R+1;s^t^1;s>>=1,t>>=1){ 34 if(~s&1) ++p[s^1]; 35 if( t&1) ++p[t^1]; 36 } 37 } 38 void pushdown(){ 39 for(int i=1;i<N;i++){ 40 add[i<<1]+=add[i]; 41 add[i<<1|1]+=add[i]; 42 p[i<<1]+=p[i]; 43 p[i<<1|1]+=p[i]; 44 } 45 } 46 47 int main(){ 48 while(scanf("%d%d",&n,&k)!=EOF){ 49 for(int i=cn=0;i<n;i++){ 50 scanf("%d%d",&l[i],&r[i]); 51 c[++cn]=l[i]; 52 c[++cn]=r[i]; 53 } 54 discrete(); 55 build(cn); 56 for(int i=0;i<n;i++){ 57 update(getid(l[i]),getid(r[i])); 58 } 59 pushdown(); //下推!! 60 //统计 61 int flag=0,cnt=0; 62 for(int i=1;i<=cn;i++){ 63 if(add[N+i]>=k){ 64 if(!flag){ //左端点 65 l[++cnt]=c[i]; 66 flag=1; 67 } 68 }else{ 69 if(flag){ //右端点 70 r[cnt]=c[i]; 71 flag=0; 72 }else { 73 if(p[N+i]>=k){ 74 l[++cnt]=c[i]; 75 r[cnt]=c[i]; 76 } 77 } 78 } 79 } 80 printf("%d ",cnt); 81 for(int i=1;i<=cnt;i++){ 82 printf("%d %d ",l[i],r[i]); 83 } 84 } 85 return 0; 86 }
Glass Carving
题意:分割矩形,求最大面积。
dalao题解http://blog.csdn.net/zearot/article/details/44759437
感觉有点无法驾驭。。。这个树有点反常。。。
好像是最后一层没有留首尾两个点,又因为0到n不可能被切(没有意义),所以只需保存1到n-1这些点,又把这些点左移一位,0到n-2。所以修改时也要左移一位。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=200010; 4 int flag[maxn<<2][2]; //标价是否全是0 5 int L[maxn<<2][2]; //左连续零 6 int R[maxn<<2][2]; //右连续零 7 int maxx[maxn<<2][2]; //最长连续零 8 int M[2]; 9 10 void pushup(int rt,int k){ 11 flag[rt][k]=flag[rt<<1][k]&&flag[rt<<1|1][k]; 12 maxx[rt][k]=max(max(maxx[rt<<1][k],maxx[rt<<1|1][k]),R[rt<<1][k]+L[rt<<1|1][k]); 13 L[rt][k]=flag[rt<<1][k]?L[rt<<1][k]+L[rt<<1|1][k]:L[rt<<1][k]; 14 R[rt][k]=flag[rt<<1|1][k]?R[rt<<1|1][k]+R[rt<<1][k]:R[rt<<1|1][k]; 15 } 16 void build(int n,int k){ 17 M[k]=1; 18 while(M[k]<n) M[k]<<=1; 19 for(int i=0;i<M[k];i++) L[M[k]+i][k]=R[M[k]+i][k]=maxx[M[k]+i][k]=flag[M[k]+i][k]=i<n; 20 for(int i=M[k]-1;i>0;i--) pushup(i,k); 21 } 22 void update(int c,int k){ 23 int s=M[k]+c-1; 24 flag[s][k]=maxx[s][k]=L[s][k]=R[s][k]=0; 25 for(s>>=1;s;s>>=1) pushup(s,k); 26 } 27 int main(){ 28 int h,w,n; 29 while(scanf("%d%d%d",&w,&h,&n)!=EOF){ 30 build(h-1,0); 31 build(w-1,1); 32 char s[5];int v; 33 for(int i=0;i<n;i++){ 34 scanf("%s%d",s,&v); 35 s[0]=='H'?update(v,0):update(v,1); 36 printf("%lld ",(long long)(maxx[1][0]+1)*(maxx[1][1]+1)); 37 } 38 } 39 40 }
A Simple Task
再补吧=_=||