注意:这是一篇十分劣质的博客,只有题目和简单的几句话,慎用。。。。。。。。。。OVO
分块
入门推荐:http://hzwer.com/8053.html
bzoj2957
这个题有线段树和分块两种做法;
线段树维护了区间的答案合并的时候维护高度最大值,右区的左子区间进一步讨论对分类讨论;
分块就对每个块维护一个可看到的上升序列,lower_bound即可;
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define il inline 4 #define rg register 5 using namespace std; 6 const int N=100010,M=610; 7 int n,m,bl[N],u,t[M],len; 8 double a[N],g[M][M]; 9 il int find(int i,double x){ 10 int l=1,r=t[i]+1; 11 while(l<r){ 12 int mid=(l+r)>>1; 13 if(x<g[i][mid])r=mid; 14 else l=mid+1; 15 } 16 return l; 17 } 18 il void update(int x){ 19 int l=(bl[x]-1)*u+1,r=bl[x]*u; 20 t[bl[x]]=0; 21 for(rg int i=l;i<=r;i++) 22 if(g[bl[x]][t[bl[x]]]<a[i])g[bl[x]][++t[bl[x]]]=a[i]; 23 double mx=0; int ans=0; 24 for(rg int i=1;i<=len;i++){ 25 int p = find(i,mx); 26 ans += t[i]-p+1; 27 if(mx<g[i][t[i]])mx=g[i][t[i]]; 28 } 29 printf("%d\n",ans); 30 } 31 il char gc(){ 32 static char *p1,*p2,s[1000000]; 33 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 34 return(p1==p2)?EOF:*p1++; 35 } 36 il int rd(){ 37 int x=0; char c=gc(); 38 while(c<'0'||c>'9')c=gc(); 39 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); 40 return x; 41 } 42 int main(){ 43 // freopen("bzoj2957.in","r",stdin); 44 // freopen("bzoj2957.out","w",stdout); 45 n=rd(); m=rd(); 46 u=550; 47 for(rg int i=1;i<=n;i++)bl[i]=(i-1)/u+1; 48 len=bl[n]; 49 for(rg int i=1;i<=n;i++)a[i]=-1; 50 for(rg int i=1,x,y;i<=m;i++){ 51 x=rd(),y=rd(); 52 a[x]=1.0*y/x; 53 update(x); 54 } 55 return 0; 56 }