【每日一题】糖糖别胡说,我真的不是签到题目(思维+枚举+前缀和)
糖糖别胡说,我真的不是签到题目
https://ac.nowcoder.com/acm/problem/14583
Solution
知识点:枚举/暴力+前缀和+思维
因为只要在队列后面出现能力值大于自己的能力值且与自己不是同一个阵营的自己就会去世,加上前 i-1 秒发功增加的能力值不会影响第 i 秒,所以可以考虑一下倒着遍历 n 秒,边枚举边更新最后面的最大值,这样的话复杂度最坏情况是,考虑用前缀和优化把能力值加在每个能力者这一过程,可以达到。
Code
#include<bits/stdc++.h> #define mp make_pair #define pb push_back #define ll long long #pragma GCC optimize(2) #define io std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) using namespace std; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;} void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); } ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a = (a*a)%p;b >>= 1;}return ans%p;} const int mo=998244353; const int mod=1000000007; const int manx=5e4+5; ll pos[manx],val[manx],s[manx]; int main(){ ll p=read(); while(p--){ ll n=read(),m=read(); for(int i=1;i<=n;i++) pos[i]=read(),val[i]=read(),s[i]=0; for(int i=1;i<=m;i++) s[read()]++; ll cnt=0,max0=0,max1=0; for(int i=n;i>=1;i--){ s[i]+=s[i+1]; val[i]+=s[i]; if(pos[i]){ if(val[i]>max1) max1=val[i]; if(val[i]<max0) cnt++; } else{ if(val[i]>max0) max0=val[i]; if(val[i]<max1) cnt++; } } printf("%lld\n",n-cnt); } return 0; }