Vases and Flowers

来源:互联网 发布:postgresql mysql迁移 编辑:程序博客网 时间:2024/06/05 21:42

这道题目很多人用二分+线段树来做,但是(可能我太水了吧)想不到怎么用二分,只好照着常规思路来做

题意:

两种操作:1.从a号花瓶开始插入f朵花,每个花瓶只能有一朵花,且有花的花的花瓶不能被放入 2.清除一个区间内花瓶中的花 注意花瓶的编号是0~n-1

解题思路:

这就是两种不同的区间更新,先设置一个结构体

struct list{int num;int weight;}tree[4*maxn];
num表示在left和right范围内花瓶中的花的数量,weight权值1表示这个范围内花瓶中都有花,-1表示花瓶中都没有花,0表示有的花瓶中有花有的没有

四个线段树函数:

void build(int i,int left,int right);void update_add(int i,int left,int right);void update_del(int i,int ql,int qr,int left,int right);void pushup(int i,int left,int right);void pushdown(int i,int left,int right);
build函数将tree数组中的num赋值为0,weight赋值为-1,表示起初花瓶都是空的,update_add函数计算添加花的情况,update_del函数计算去除花的情况,pushup函数更新父节点,pushdown函数更新子节点

if(op==1){scanf("%d%d",&L,&ans);L++;R=L+ans-1;l=-1,r=-1;update_add(1,1,n);if(r==-1)printf("Can not put any one.\n");elseprintf("%d %d\n",l-1,r-1);}
插花的操作,因为花瓶的编号可能为零所以将更新的左边界+1,而右边界是可以改变,随着插花向右增大,最大为n

else if(op==2){int a,b;scanf("%d%d",&a,&b);ans=0;update_del(1,a+1,b+1,1,n);printf("%d\n",ans);}
丢花的操作就是一个区间更新,注意边界都要+1

void update_add(int i,int left,int right){if(ans<=0)return ;if(r==n)return ;if(L<=left&&R>=right&&tree[i].weight){if(!tree[i].num){if(l<0)l=left;if(right>r)r=right;ans-=right-left+1;tree[i].num=right-left+1;tree[i].weight=1;}else{R+=(right-left+1);if(R>n)R=n;}return ;}if(tree[i].weight)pushdown(i,left,right);int mid=(left+right)>>1;if(L<=mid)update_add(i<<1,left,mid);if(R>mid)update_add(i<<1|1,mid+1,right);pushup(i,left,right);}
最关键的是第三个if语句中的,如果逻辑不好就有超时的风险,简单说一下,当这个区间在L和R内且全为1或0时,执行内部的语句,如果全为0,就把花插上更新起点、终点,如果全为1,就就扩大右边界(最大为n)

Alice有N个花瓶(标号为0~ N-1)。当她收到一些花时,她会随机的选择一个瓶子A,从它开始遍历A,A+1, A+2, ..., N-1号瓶子,遇到空瓶子就放一朵花进去,直到花朵放完或没有瓶子,剩下的花将被丢弃。有时,她也会清理标号从A到B的花瓶(A <= B).花瓶里的花会被丢弃。
Input

  第一行一个整数T,表示数据组数。
  每组数据,第一行一个整数N(1 < N < 50001) and M(1 < M < 50001). N 是花瓶个数,  M 是Alice的操作次数. 接下来M行 行3个 整数. 第一个整数K(1 or 2). 如果K=1, 后面跟两个整数 A 和  F . 表示Alice 得到了F 朵花并且把它们放入从A 的花瓶里. 如果K= 2, 后跟两个整数 A 和  B. 表示Alice  清理的花瓶标号范围(A <= B).

Output

  对于每个K=1的操作,输出第一朵和最后一朵花放置的花瓶标号。如果没有任何放花的位置,输出'Can not put any one.'.对于K=2的操作,输出丢弃花的个数.
   每组数据后输出一个空行.

Sample Input
210 51 3 52 4 51 1 82 3 61 8 810 61 2 52 3 41 0 82 2 51 4 41 2 3
Sample Output
3 721 94Can not put any one.2 620 944 52 3


#include<stdio.h>#include<string.h>#define maxn 50005struct list{int num;int weight;}tree[4*maxn];int ans,l,r,n,L,R;void build(int i,int left,int right);void update_add(int i,int left,int right);void update_del(int i,int ql,int qr,int left,int right);void pushup(int i,int left,int right);void pushdown(int i,int left,int right);int main(){int t;scanf("%d",&t);while(t--){int m;scanf("%d%d",&n,&m);build(1,1,n);for(int i=0;i<m;i++){int op;scanf("%d",&op);if(op==1){scanf("%d%d",&L,&ans);L++;R=L+ans-1;l=-1,r=-1;update_add(1,1,n);if(r==-1)printf("Can not put any one.\n");elseprintf("%d %d\n",l-1,r-1);}else if(op==2){int a,b;scanf("%d%d",&a,&b);ans=0;update_del(1,a+1,b+1,1,n);printf("%d\n",ans);}}putchar('\n');}return 0;}void build(int i,int left,int right){tree[i].num=0;tree[i].weight=-1;if(left==right)return ;int mid=(left+right)>>1;build(i<<1,left,mid);build(i<<1|1,mid+1,right);}void update_add(int i,int left,int right){if(ans<=0)return ;if(r==n)return ;if(L<=left&&R>=right&&tree[i].weight){if(!tree[i].num){if(l<0)l=left;if(right>r)r=right;ans-=right-left+1;tree[i].num=right-left+1;tree[i].weight=1;}else{R+=(right-left+1);if(R>n)R=n;}return ;}if(tree[i].weight)pushdown(i,left,right);int mid=(left+right)>>1;if(L<=mid)update_add(i<<1,left,mid);if(R>mid)update_add(i<<1|1,mid+1,right);pushup(i,left,right);}void update_del(int i,int ql,int qr,int left,int right){if(ql<=left&&qr>=right){ans+=tree[i].num;tree[i].num=0;tree[i].weight=-1;return ;}if(tree[i].weight)pushdown(i,left,right);int mid=(left+right)>>1;if(ql<=mid)update_del(i<<1,ql,qr,left,mid);if(qr>mid)update_del(i<<1|1,ql,qr,mid+1,right);pushup(i,left,right);}void pushup(int i,int left,int right){tree[i].num=tree[i<<1].num+tree[i<<1|1].num;if(tree[i<<1].num+tree[i<<1|1].num==right-left+1)tree[i].weight=1;else if(tree[i<<1].num+tree[i<<1|1].num==0)tree[i].weight=-1;}void pushdown(int i,int left,int right){if(tree[i].weight==1){tree[i<<1].weight=1;tree[i<<1|1].weight=1;int mid=(left+right)>>1;tree[i<<1].num=mid-left+1;tree[i<<1|1].num=right-mid;tree[i].weight=0;}else if(tree[i].weight==-1){tree[i<<1].weight=-1;tree[i<<1|1].weight=-1;tree[i<<1].num=0;tree[i<<1|1].num=0;tree[i].weight=0;}}






原创粉丝点击