线段树+ 区间更新
题目链接:https://cn.vjudge.net/problem/HDU-4614
又是一个改了两天的代码。。。。原来数组开小了也会报超时。
具体思路:按照区间更新的思路打就可以了,不过有很多可以优化的地方,具体见代码。
AC代码:
#include<iostream>
#include<string>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<stdio.h>
#include<algorithm>
#include<set>
using namespace std;
# define inf 0x3f3f3f3f
# define maxn 1000001
# define ll long long
# define lson l,m,rt<<1
# define rson m+1,r,rt<<1|1
int a[maxn*10];
int col[maxn*10];
int flag;
int le,ri;
int t1,t2,t3;
int temp;
int k;
void up(int rt)
{
a[rt]=a[rt<<1]+a[rt<<1|1];
}
void down(int rt,int l,int r)
{
if(col[rt]!=-1)
{
col[rt<<1]=col[rt<<1|1]=col[rt];
int mid=(r+l)/2;
a[rt<<1]=(mid-l+1)*col[rt];//注意,a数组存的是这个节点往下有多少多话,所以复制的时候需要注意区间长度。
a[rt<<1|1]=(r-mid)*col[rt];
//a[rt<<1]=a[rt<<1|1]=a[rt];
col[rt]=-1;
}
}
void buildtree(int l,int r,int rt)
{
a[rt]=0;
col[rt]=-1;
if(l==r)return ;
int m=(l+r)>>1;
buildtree(lson);
buildtree(rson);
}
void update(int L,int R,int l,int r,int rt)
{
if(t3<=0)return ;
if(L<=l&&R>=r)
{
if(t1==1)//如果是插花
{if(r-l+1==a[rt])return ;//如果这个区间已经插满了,返回,优化
if(a[rt]==0&&t3>=(r-l+1))//当前的区间都能插花再更新
{
col[rt]=1;
flag=1;
a[rt]=r-l+1;
le=min(l,le);
ri=max(r,ri);
t3-=(r-l+1);
return ;
}
}
else if(t1==2)
{
temp+=a[rt];//先把原来的和求好了,这样就能省一个查询的过程。
a[rt]=0;
col[rt]=0;
return ;
}
// if(l==r)return ;
}
down(rt,l,r);
int m=(l+r)>>1;
if(L<=m)update(L,R,lson);
if(R>m)update(L,R,rson);
up(rt);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
buildtree(1,n,1);//初始化
while(m--)
{
flag=0;
le=inf,ri=0;
scanf("%d%d%d",&t1,&t2,&t3);
t2++;
if(t1==1)
{
update(t2,n,1,n,1);
if(flag==0)
{
printf("Can not put any one.\n");
continue;
}
else
{
printf("%d %d\n",le-1,ri-1);
}
}
else if(t1==2)
{
t3++;
temp=0;
update(t2,t3,1,n,1);
printf("%d\n",temp);
}
}
printf("\n");
}
return 0;
}