1 4 3 0 3 1 2 0 3 1 1 1 3 4
3HintAfter the first seconds,b1=4,b2=2,b3=3,b4=1 After the second seconds,b1=4,b2=2,b3=3,b4=1 After the third seconds,b1=5,b2=3,b3=4,b4=1,and the second GT is annihilated by the third one. After the fourth seconds,b1=6,b2=4,b3=5,b4=2 ci is unordered.
/************************************************************************/
附上该题对应的中文题
从前,有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
3
第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并不是有序的
出题人的解题思路:
首先这道题有一个很显然的O(n∗logn)的做法,直接区间加,求区间最大值即可。 但是此题还有一个O(n)的做法。我们发现b1,b2,...,bx都加1就相当于bx+1,bx+2,...,bn都减1。然后我们可以倒着做,记一下最大值,如果遇到了修改操作,就把最大值减1,然后判断一下这个人会不会被消灭掉,然后再更新一下最大值。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 50005; const int M = 710; const int inf = 1000000000; const int mod = 1000000007; int a[N],b[N]; int c[N]; multiset<int> s1,s2; multiset<int>::iterator it; int main() { int t,n,m,i,k,x,sum1,sum2; scanf("%d",&t); while(t--) { s1.clear();s2.clear(); memset(c,0,sizeof(c)); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); for(i=0;i<m;i++) { scanf("%d",&x); c[x]++; } sum1 = sum2 = 0; for(i=1,k=0;i<=n;i++) { b[i] -= k; if(a[i]==0) { if(!s2.empty()) for(it=s2.begin();it!=s2.end();) if(b[i]> *it){ s2.erase(it),sum2--; it = s2.begin(); } else break; s1.insert(b[i]); sum1++; } else if(a[i]==1) { if(!s1.empty()) for(it=s1.begin();it!=s1.end();) if(b[i]> *it){ s1.erase(it); sum1--; it = s1.begin(); } else break; s2.insert(b[i]); sum2++; } if(c[i]) k += c[i]; } printf("%d\n",sum1+sum2); } return 0; }菜鸟成长记