昨天上课老师讲尽量把学过的知识点总结一下,,,以后尽量写写博客吧,
-
Vases and Flowers
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614
看到花瓶只有放花不放花这两种状态,应该很快就可以想到01代替状态,
操作2中的求一段区间中有花的瓶数就可以转化为求区间和问题,
操作1中要求区间x~n中,满足有 y个0的第一个区间左右端点。(第一个0的位置,最后一个0的位置)
如果没有0就输出can't,(这里求一个区间和就可以了)
怎么找到区间里第一个0?
一段区间内0的个数肯定是递增的,
那么二分查找第一个满足区间内1的个数和为1的位置,
最后一个零的位置同理。
#include<cstdio> #include<string> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int MAXN=5e4+10; #define INF 0x3f3f3f3f #define endll printf("\n") #define s1(a) scanf("%d",&a) #define s2(a,b) scanf("%d %d",&a,&b) #define mem(a,b) memset(a,b,sizeof(a)) #define s3(a,b,c) scanf("%d %d %d",&a,&b,&c)int n,m; int tr[MAXN<<4]; int cov[MAXN<<4]; void pushdown(int rt,int l,int r) { int ls=rt<<1,rs=rt<<1|1; int mid=(l+r)>>1; cov[ls]=cov[rs]=cov[rt]; if(cov[rt]==0) tr[ls]=tr[rs]=0; else { tr[ls]=mid-l+1; tr[rs]=r-mid; } cov[rt]=-1; } int quesum(int x,int y,int rt,int l,int r) { if(x>r||y<l) return 0; if(x<=l&&y>=r) return tr[rt]; if(cov[rt]!=-1) pushdown(rt,l,r); int mid=(l+r)>>1; int ans=0; ans+=quesum(x,y,rt<<1,l,mid); ans+=quesum(x,y,rt<<1|1,mid+1,r); return ans; } int quezero(int x,int y,int cnt) { int l=x,r=y; while(l<r) { int mid=(l+r)>>1; int temp=mid-x+1-quesum(x,mid,1,1,n); if(temp>=cnt)// r=mid; else l=mid+1; } return l; } void update(int x,int y,int v,int rt,int l,int r) { if(x>r||y<l) return; if(x<=l&&y>=r) { tr[rt]=v*(r-l+1); cov[rt]=v; return; } if(cov[rt]!=-1) pushdown(rt,l,r); int mid=(l+r)>>1; update(x,y,v,rt<<1,l,mid); update(x,y,v,rt<<1|1,mid+1,r); tr[rt]=tr[rt<<1]+tr[rt<<1|1]; } int main() { int t;s1(t); while(t--) { s2(n,m); mem(tr,0);mem(cov,-1); for(int i=0;i<m;i++) { int f,x,y; s3(f,x,y); if(f==1) { x++; int zero=n-x+1-quesum(x,n,1,1,n); if(zero==0) printf("Can not put any one.\n"); else { int u=quezero(x,n,1); int v=quezero(u,n,min(y,zero)); printf("%d %d\n",u-1,v-1); update(u,v,1,1,1,n); } } else { x++;y++; printf("%d\n",quesum(x,y,1,1,n)); update(x,y,0,1,1,n); } } endll; } return 0; }