您的位置:首页 > 其它

hdu-4614Vases and Flowers 线段树区间赋值

2013-08-11 23:00 162 查看
题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=4614

题目是说给你一个区间然后初始值为0就是代表没有花

给你两种操作1 代表从A开始插F只花 花盆为空就查  不为空就往下一个推 直到花插完为止 如果一朵花都能插  就输出Can not put...

如果能就输出第一个插花位置 和最后一个插花位置, 多出来的花扔掉

2 代表把区间A,B 的花全部扔掉 要你输出扔掉的花有多少

题目就这样 ,我也不知道为啥一开始WA了十几次  花了一个晚上 最终换思路重写一遍过掉

后来发现AC的代码 如果插花F=0 竟然是要顺推把那个位置占掉  虽然我也不知道测试数据F 会不会等于0   =0=

思路就是先找出最左边的第一个能插花的位置first  再找出最右边的位置last

然后用了lazy标记用于区间操作 cover( 1, first ,last ,1);

其他也就没什么了

#include <iostream>
#include <cstdio>
#include <cstring>
#define MAX 100010
using namespace std;
typedef struct
{
int l;
int r;
int sum;
int cov;
} Tree;
Tree tree[MAX*10];
int N,M,ch,A,B,K,last,first;
void update(int i)
{
if(tree[i].cov!=-1)
{
tree[i].sum=(tree[i].r-tree[i].l+1)*tree[i].cov;
tree[i*2].cov=tree[i].cov;
tree[i*2+1].cov=tree[i].cov;
tree[i].cov=-1;
}
}
int build(int i,int l,int r)
{
int mid;
tree[i].l=l;
tree[i].r=r;
tree[i].sum=0;
tree[i].cov=-1;
if(l==r)
return 0;
mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
int cover(int i,int x,int y,int now)
{
int mid;
update(i);
if((x<=tree[i].l)&&(y>=tree[i].r))
{
tree[i].cov=now;
return 0;
}
mid=(tree[i].l+tree[i].r)/2;
if(x<=mid) cover(i*2,x,y,now);
if(y>mid) cover(i*2+1,x,y,now);
update(i*2);
update(i*2+1);
tree[i].sum=(tree[i*2].sum+tree[i*2+1].sum);
}
int cal(int i,int x,int y)
{
int mid;
int ans;
update(i);
if ((x<=tree[i].l)&&(y>=tree[i].r))
return (tree[i].sum);
ans=0;
mid=(tree[i].l+tree[i].r)/2;
if (x<=mid) ans=(ans+cal(i*2,x,y));
if (y>mid) ans=(ans+cal(i*2+1,x,y));
update(i*2);
update(i*2+1);
tree[i].sum=(tree[i*2].sum+tree[i*2+1].sum);
return ans;
}
int findfirst(int i,int x) //firs比较好找
{
int mid=(tree[i].l+tree[i].r)/2;
if(tree[i].l==tree[i].r)
return tree[i].l;
if(x>mid)
findfirst(i*2+1,x);
else
{
int sum=cal(i*2,x,tree[i*2].r);
if(sum==tree[i*2].r-x+1)
findfirst(i*2+1,mid+1);
else
findfirst(i*2,x);
}

}
int findlast(int i,int x,int k)
{
int mid=(tree[i].l+tree[i].r)/2;
if(tree[i].r==tree[i].l)
return tree[i].l;
if(mid<x) //如果x> mid 直接右转
findlast(i*2+1,x,k);
else
{
int sum=cal(i*2,x,tree[i*2].r);
int canputl=tree[i*2].r-x+1-sum;
int canputr=tree[i*2+1].r-tree[i*2+1].l+1- cal(i*2+1,mid+1,tree[i*2+1].r);
if(canputl==0)
findlast(i*2+1,mid+1,k);
else if(canputr==0) //这个是重点
findlast(i*2,x,k);
else
{
if(canputl<k)
findlast(i*2+1,mid+1,k-canputl);
else if(canputl>=k)
findlast(i*2,x,k);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
build(1,0,N-1);
while(M--)
{
scanf("%d",&ch);
switch(ch)
{
case 1:
{
scanf("%d%d",&A,&K);
if(A>=N||cal(1,A,N-1)==N-A)
printf("Can not put any one.\n");
else
{
first=findfirst(1,A);
last=findlast(1,A,K);
printf("%d %d\n",first,last);
cover(1,first,last,1);
}
break;

}
case 2:
{
scanf("%d%d",&A,&B);
printf("%d\n",cal(1,A,B));
cover(1,A,B,0);
break;
}
}
}
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 lazy标记 hdu