HDOJ 5596 GTW likes gt (线段树区间更新+单点查询+技巧)

GTW likes gt

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 609    Accepted Submission(s): 210


Problem Description
Long long ago, there were n adorkable GT. Divided into two groups, they were playing games together, forming a column. The ith GT would randomly get a value of ability bi . At the ith second, the ith GT would annihilate GTs who are in front of him, whose group differs from his, and whose value of ability is less than his.

In order to make the game more interesting, GTW, the leader of those GTs, would emit energy for m times, of which the ith time of emitting energy is ci . After the ci second, b1,b2,...,bci would all be added 1.

GTW wanted to know how many GTs would survive after the nth second.
 

Input
The first line of the input file contains an integer T(5) , which indicates the number of test cases.

For each test case, there are n+m+1 lines in the input file.

The first line of each test case contains 2 integers n and m , which indicate the number of GTs and the number of emitting energy, respectively. (1n,m50000)

In the following n lines, the ith line contains two integers ai and bi , which indicate the group of the ith GT and his value of ability, respectively. (0ai1,1bi106)

In the following m lines, the ith line contains an integer ci , which indicates the time of emitting energy for ith time.
 

Output
There should be exactly T lines in the output file.

The ith line should contain exactly an integer, which indicates the number of GTs who survive.
 

Sample Input
  
  
1 4 3 0 3 1 2 0 3 1 1 1 3 4
 

Sample Output
  
  
3
Hint
After the first seconds,$b_1=4,b_2=2,b_3=3,b_4=1$ After the second seconds,$b_1=4,b_2=2,b_3=3,b_4=1$ After the third seconds,$b_1=5,b_2=3,b_3=4,b_4=1$,and the second GT is annihilated by the third one. After the fourth seconds,$b_1=6,b_2=4,b_3=5,b_4=2$ $c_i$ is unordered.
ac
 

题意:
从前,有n只萌萌的GT,他们分成了两组在一起玩游戏。他们会排列成一排,第i只GT会随机得到一个能力值bi。在
第i秒的时候,第i只GT可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的GT。为了使游戏更加有趣,
GT的首领GTW会发功m次,第i次发功的时间为ci,则在第ci秒结束后,b1,b2,...,bci都会增加1。现在,GTW想知道在
第n秒之后,会有几只GT存活下来。
思路:先用线段树给m次发功更新一下区域,然后倒着找,而且定义两个最值,分别代表两个阵营的最大值,然后如果前面的能力值大于此最大值,那么ans加一,说明能存活,同时,更新另一个最大值,复杂度nlogn


ac代码:
#include<stdio.h>
#include<string.h>
#define MAXN 1000010
int max(int a,int b)
{
	return a>b?a:b;
}
struct s
{
	int left;
	int right;
	int sum; 
	int lazy;
}tree[4000000+1000];
int a[MAXN],b[MAXN];
void pushdown(int i)
{
	if(tree[i].lazy)
	{
		tree[i*2].sum+=tree[i].lazy*(tree[i*2].right-tree[i*2].left+1);
		tree[i*2+1].sum+=tree[i].lazy*(tree[i*2+1].right-tree[i*2+1].left+1);
		tree[i*2].lazy+=tree[i].lazy;
		tree[i*2+1].lazy+=tree[i].lazy;
		tree[i].lazy=0;
	}
}
void build(int l,int r,int i)
{
	int mid;
	tree[i].left=l;
	tree[i].right=r;
	tree[i].lazy=0;
	if(l==r)
	{
		tree[i].sum=0;
		return;
	} 
	mid=(l+r)/2;
	build(l,mid,i*2);
	build(mid+1,r,i*2+1);
	tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
void update(int l,int r,int c,int i)
{
	int mid;
	if(tree[i].left==l&&tree[i].right==r)
	{
		tree[i].lazy+=c;
		tree[i].sum+=c*(r-l+1);
		return;
	}
	pushdown(i);
	mid=(tree[i].left+tree[i].right)/2;
	if(r<=mid)
	update(l,r,c,i*2);
	else if(l>mid)
	update(l,r,c,i*2+1);
	else
	{
		update(l,mid,c,i*2);
		update(mid+1,r,c,i*2+1);
	}
	tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
int query(int a,int i)
{
	if(tree[i].left==a&&tree[i].right==a)
	return tree[i].sum;
	pushdown(i);
	int mid=(tree[i].left+tree[i].right)/2;
	if(a<=mid)
	return query(a,i*2);
	else if(a>mid)
	return query(a,i*2+1);
}
int main()
{
	int i,n,m;
	int t,c;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		build(1,n,1);
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&a[i],&b[i]);
			update(i,i,b[i],1);//初始能量值
		}
		for(i=0;i<m;i++)
		{
			scanf("%d",&c);
			update(1,c,1,1);//区间更新能量值
		}
		for(i=1;i<=n;i++)
	    b[i]=query(i,1);//查询最后的能量值
		int ans=0;
		int M1=-1,M2=-1;
		for(i=n;i>0;i--)
		{
			if(a[i]==1)
			{
				if(b[i]>=M2)
				ans++;
				M1=max(M1,b[i]);
			}
			else
			{
				if(b[i]>=M1)
				ans++;
				M2=max(M2,b[i]);
			}
		}
		printf("%d\n",ans);
    }
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值