题意:n个糖糖排成一排,每个糖糖有一个能力值,第i秒第i个糖糖就会杀死前面能力比他小的人,进行m次区间加的操作,每次输入ci,表示第ci秒1~ci的糖糖能力值加一,输出最后有多少糖糖存活。
思路:
1.前m次操作可以用前缀和模拟区间加,得到每个糖糖的新能力值后从后往前维护每个队伍的最大值,当前糖糖的能力值如果大于后面敌对队伍糖糖的最大值,也就是比后面的糖糖都强,那么他存活,反之白给。复杂度 (n)。
2.如果从前往后判断第i糖糖能不能存活,还要搜索后面i-1个糖糖,复杂度 (n^2)。
3.刚开始没看懂题目看大佬博客,整了一个后缀和,一下愣是没看懂,看了2个多小时才看懂,你信?,大佬还提到扩展到n个队伍,维护一个最大值一个最小值,并保证两个不属于同一支队伍即可,复杂度也可以做到 (n)。思路差不多。
Code:
#include<bits/stdc++.h> #define js ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) using namespace std; int mx[2],sum[50005],b[50005],team[50005],n,m,t,c; int main() { js; cin>>t; while(t--) { cin>>n>>m; memset(sum,0,sizeof sum); for(int i=1;i<=n;++i) cin>>team[i]>>b[i]; for(int i=1;i<=m;++i) { cin>>c; ++sum[c]; } mx[team[n]]=b[n]+sum[n]; mx[team[n]^1]=0; int cnt=1; for(int i=n-1;i;--i) { sum[i]+=sum[i+1]; if(sum[i]+b[i]>=mx[team[i]^1]) ++cnt; mx[team[i]]=max(mx[team[i]],sum[i]+b[i]); } cout<<cnt<<endl; } }