Codeforces Round 1032 (Div. 3) F. Yamakasi
F. Yamakasi
题目: F. Yamakasi
思路:
题目问和为 s 且区间最大值为 x 的区间数量,不难想到以 x 为遍历的主角,以两边不超过 x 的范围为边界,在这个范围里去下手。找边界(左右两边第一个大于/大于等于 x 的位置)为单调栈模板。
-
预处理好每个 x 的范围后,对于合法范围
[l, r]内的点,记sum[]为前缀和,i遍历 x 的位置id到r,即是要找前缀和为\(sum[j-1] = sum[i] - s\)的位置j-1(这样区间范围才是j到i)。这里二分找到第一个大于等于l-1的位置L,第一个大于等于id的位置R,贡献就是R - L。 -
这样需要注意一个问题,当有多个 x 的时候,会存在重复的问题,比如
... x ... x ... x时,对于第二个 x,可能选择区间的时候会选到第三个 x,到时第三个 x 又会选到第二个 x。针对这种情况,做过的题目也不少,选择区间一闭一开即可,我这里采用左边界找第一个大于等于 x 的,右边界找第一个大于 x 的,这样就不会有重复性问题了。
代码
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+ 1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
ll a[maxn];
ll l[maxn], r[maxn], sum[maxn];
ll n,s,x;
map<ll,vector<ll> > Map;
void init()
{
Map.clear();
stack<ll> s;
Map[0].pb(0);
rep(i,1,n)
{
while(s.size()&&a[s.top()]<=a[i]) s.pop();
if(s.size()) l[i] = s.top();
else l[i] = 0;
s.push(i);
sum[i] = sum[i-1] + a[i];
Map[sum[i]].pb(i);
}
while(s.size()) s.pop();
per(i,n,1)
{
while(s.size()&&a[s.top()]<a[i]) s.pop();
if(s.size()) r[i] = s.top();
else r[i] = n+1;
s.push(i);
}
}
ll cal(ll l, ll id, ll r)
{
ll ans = 0;
rep(i,id,r)
{
ll k = sum[i] - s; // j-1
if(!Map.count(k)) continue;
ll id1 = lower_bound(Map[k].begin(),Map[k].end(),l-1) - Map[k].begin();
ll id2 = lower_bound(Map[k].begin(),Map[k].end(),id) - Map[k].begin();
ans += id2-id1;
}
return ans;
}
void sol()
{
n = read(), s = read(), x = read();
rep(i,1,n) a[i] = read();
init();
ll nxt = 0, ans = 0;
rep(i,1,n)
{
if(i<=nxt||a[i]!=x) continue;
ans += cal(l[i]+1,i,r[i]-1);
nxt = r[i]-1;
}
printf("%lld\n",ans);
}
int main()
{
int kase;
cin>>kase;
while(kase--) sol();
return 0;
}
}

浙公网安备 33010602011771号