GTW likes gt
Accepts: 54 Submissions: 782 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) 问题描述从前,有n只萌萌的GT,他们分成了两组在一起玩游戏。他们会排列成一排,第i只GT会随机得到一个能力值bi。在第i秒的时候,第i只GT可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的GT。输入描述
为了使游戏更加有趣,GT的首领GTW会发功m次,第i次发功的时间为ci,则在第ci秒结束后,b1,b2,...,bci都会增加1。
现在,GTW想知道在第n秒之后,会有几只GT存活下来。
第一行只有一个整数T(T≤5),表示测试数据组数。输出描述
第二行有两个整数n,m。表示GT的个数和GTW发功的次数。(1≤n≤50000,1≤m≤50000)
第三到n+2行,每行有两个整数ai,bi,表示第i只GT在哪个组和他的能力值 (0≤a[i]≤1,1≤b[i]≤106)
第n+3行到第n+m+2行,每行有一个整数ci,表示GTW第i次发功的时间。1≤c[i]≤n
总共T行,第i行表示第i组数据中,GT存活的个数。输入样例
1输出样例
4 3
0 3
1 2
0 3
1 1
1
3
4
3Hint
第1秒后 能力值为4 2 3 1
第2秒后 能力值为4 2 3 1
第3秒后 能力值为5 3 4 1,第2只GT被第3只GT消灭掉了
第4秒后 能力值为6 4 5 2
ci并不是有序的
题意很明确,这里就不多啰嗦了。
这里详说一下我的解题经历和大牛代码的解题思想。
首先看到题意 ,小白嘛,当然是想用暴力或者模拟思路去搞定这
int a[50050];
int b[50050];
int fagong[50050];
memset(fagong,0,sizeof(fagong));
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i],&b[i]);
}
for(int i=0;i<m;i++)
{
int k;
scanf("%d",&k);
fagong[k]++;//题意是说可以发功多次~。所以这里每出现一次,我们就要+1.
}
个题目,但是读题目中的数据范围的时候,就知道这个方法根本不可行。然后就想到了用线段树,多次操作,单次查询。这里用线段树可解。然后我就敲啊敲啊,敲出了我的线段树,但是不巧TLE,我估计是后台数据比较强大的一放面,并且自己线段树的代码中数据的操作可能有错误,再一个就是可能是代码这么做确实可以超时,不管如何,反正没过,这里希望如果有大牛看出来我这个为什么没有AC的话还请指点。最后上我的超时代码.
还是研究了好一会,并没有摆脱TLE的命运。然后默默的去找了题解,发现这个题目的解题思路是真的很巧。
这里我们用样例来举例详解。这里我们先上初始化内容代码:
这里我们知道,最后一个GT是不会死的。另外,发功是随着比较进行的,我们这里的比较步骤是这样的:先发功,然后由当前的GT向前比较的,看看前边有没有比自己小的GT.然后干掉他。如果按照模拟去做,我们这里发功的操作的时间复杂度是O(n^2)。是一定会超时的,所以我们这里形成了这样的一个巧发功的方法:逆向思维。很多时候呢,我们正向解决问题比较困难的时候,要多逆向考虑考虑,也许发现真的可行呢~。
我们这里还是按照样例来说:
初始的b是这样的:3 2 3 1
整个操作过程完成后B是这样的:6 4 5 2.
我们不难发现,当时间变到4的时候发功之后,1-4号GT的b都要+1,但是时间变到3的时候,4号GT是不会跟着变化的,由于这个特性,我们可以逆向的去+b,就达到了降低时间复杂度的任务:
for(int i=n;i>=1;i--)b处理完毕之后,我们对其中数据进行分析:6 4 5 2。
{
fagong[i]+=fagong[i+1];
b[i]+=fagong[i];
}
首先呢,我们要知道,是要对不同阵容的比较。所以我们这里先设上两个变量:maxn,maxn1.分别表示0号阵容的最大b,和1号阵容的最大b
如果我们这里还是正向比较。复杂度还是O(n^2)所以,这里还是用上了逆向思维。如果当前b的后边的最大不同阵容的b不足以杀死当前b,那么他就生存下来了。(这一步骤很容易理解,并且也是最重要的思路。)(大牛就是大牛。。。。。小白给跪了.....)
最终我们这里就形成了近乎完美的核心思路:这里直接上代码:
int output=0;然后是完整的AC代码和我的超时线段树代码:
int maxn0=-0x1f1f1f1f;
int maxn1=-0x1f1f1f1f;
for(int i=n;i>=1;i--)
{
if(a[i]==0)//如果是0阵容的GT
{
if(maxn1<=b[i])//如果当前这只GT的身后没有任何一只GT(当然是1阵容的)能够干掉他,
output++;//那么他就生存了下来
maxn0=max(maxn0,b[i]);//实时更新身后最大值。
}
if(a[i]==1)
{
if(maxn0<=b[i])
output++;
maxn1=max(maxn1,b[i]);
}
}
printf("%d\n",output);
#include<cstdio>如果某位大牛看出了我的代码哪里还能优化或者是错误了的话,请您务必指出:
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a[50050];
int b[50050];
int fagong[50050];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(fagong,0,sizeof(fagong));
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i],&b[i]);
}
for(int i=0;i<m;i++)
{
int k;
scanf("%d",&k);
fagong[k]++;
}
for(int i=n;i>=1;i--)//NB//代替了sort并且双for.
{
fagong[i]+=fagong[i+1];
b[i]+=fagong[i];
}
int output=0;
int maxn0=-0x1f1f1f1f;
int maxn1=-0x1f1f1f1f;
for(int i=n;i>=1;i--)
{
if(a[i]==0)
{
if(maxn1<=b[i])
output++;
maxn0=max(maxn0,b[i]);
}
if(a[i]==1)
{
if(maxn0<=b[i])
output++;
maxn1=max(maxn1,b[i]);
}
}
printf("%d\n",output);
}
}
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int shuju[121212];
int tree[121212];
int flag[121212];
int bijiao[121212];
int bijiao2[121212];
int num[121212];
int fagong[121212];
int cont;
void pushup(int rt)
{
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build( int l ,int r , int rt )
{
if( l == r )
{
scanf("%d%d",&flag[rt],&shuju[rt]);
num[rt]=cont;
bijiao[cont]=shuju[rt];
bijiao2[cont]=flag[rt];
cont++;
tree[rt]=1;
return ;
}
else
{
int m = (l+r)>>1 ;
build(lson) ;
build(rson) ;
pushup(rt) ;
}
}
void update(int c,int l,int r,int rt)
{
if(l==r)
{
shuju[rt]+=c;
bijiao[num[rt]]+=c;
return ;
}
else
{
int m=(l+r)>>1 ;
update(c,lson);
update(c,rson);
}
}
void update2(int c,int c2,int p,int l,int r,int rt)
{
if(l==r)
{
if(c>shuju[rt]&&p>num[rt]&&c2!=flag[rt])
tree[rt]=0;
return ;
}
else
{
int m=(l+r)>>1 ;
update2(c,c2,p,lson);
update2(c,c2,p,rson);
pushup(rt);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(fagong,0,sizeof(fagong));
cont=0;
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
//printf("yes\n");
int fagong[10000];
for(int i=0;i<m;i++)
{
int k;
scanf("%d",&k);
k--;
fagong[k]++;
}
sort(fagong,fagong+m);
for(int i=0;i<n;i++)
{
//printf("%d\n",bijiao[i]);
if(fagong[i])update(fagong[i],1,n,1);
update2(bijiao[i],bijiao2[i],i,1,n,1);
}
printf("%d\n",tree[1]);
}
}