不知道怎么的,一个简单题我竟然用了很复杂的方法去解决他,分享一下我奇妙的解法(线段树+二分+预处理),估计很少读者能看懂吧?
#include<bits/stdc++.h>
#define int long long
#define ed '\n'
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
#define all(x) x.begin(), x.end()
#define lb(x) x&-x
using namespace std;
typedef pair<int,int>pa;
const int mod_=1e18;
const int mod=998244353;
const int g=1e6+10;
int a[g];
struct pp
{
int id;
int l;
int r;
int mx;
int mi;
}tr[g];
void build(int i,int l,int r)
{
tr[i]={i,l,r,0,mod_};
if(l==r)
{
tr[i].mx=a[l];
tr[i].mi=a[l];
return;
}
int mid=l+r>>1;
build(i+i,l,mid);
build(i+i+1,mid+1,r);
tr[i].mx=max(tr[i+i].mx,tr[i+i+1].mx);
tr[i].mi=min(tr[i+i].mi,tr[i+i+1].mi);
return;
}
int get_mx(int i,int l,int r)
{
if(tr[i].l>=l&&r>=tr[i].r)return tr[i].mx;
int mid=tr[i].l+tr[i].r>>1;
int x=0;
if(l<=mid)x=max(x,get_mx(i+i,l,r));
if(r>mid)x=max(x,get_mx(i+i+1,l,r));
return x;
}
int get_mi(int i,int l,int r)
{
if(tr[i].l>=l&&r>=tr[i].r)return tr[i].mi;
int mid=tr[i].l+tr[i].r>>1;
int x=mod_;
if(l<=mid)x=min(x,get_mi(i+i,l,r));
if(r>mid)x=min(x,get_mi(i+i+1,l,r));
return x;
}
void solve()
{
int n=0,x=0,y=0;
cin>>n>>x>>y;
for(int i=1;i<=n;i++)cin>>a[i];
vector<int>nxt_x(n+2,n+1),nxt_y(n+2,n+1);
for(int i=n;i>=1;i--)
{
if(a[i]==x)nxt_x[i]=i;
else nxt_x[i]=nxt_x[i+1];
if(a[i]==y)nxt_y[i]=i;
else nxt_y[i]=nxt_y[i+1];
}
build(1,1,n);
auto check=[&](int l,int r)->bool
{
int t1=get_mx(1,l,r),t2=get_mi(1,l,r);
if(t1!=x||t2!=y)return true;
else return false;
};
int ans=0;
for(int i=1;i<=n;i++)
{
if(a[i]==x)
{
int id=nxt_y[i];
if((id>=n+1)||(get_mi(1,i,id)!=y)||(get_mx(1,i,id)!=x))continue;
else
{
int l=id,r=n;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(i,mid))r=mid-1;
else l=mid;
}
ans+=r-id+1;
}
}
else if(a[i]==y)
{
int id=nxt_x[i];
if((id>=n+1)||(get_mi(1,i,id)!=y)||(get_mx(1,i,id)!=x))continue;
else
{
int l=id,r=n;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(i,mid))r=mid-1;
else l=mid;
}
ans+=r-id+1;
}
}
else
{
int id1=nxt_x[i],id2=nxt_y[i];
int id=max(id1,id2);
if((id>=n+1)||(get_mi(1,i,id)!=y)||(get_mx(1,i,id)!=x))continue;
else
{
int l=id,r=n;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(i,mid))r=mid-1;
else l=mid;
}
ans+=r-id+1;
}
}
}
cout<<ans<<ed;
return;
}
signed main()
{
IOS;
// freopen("in.txt","r",stdin);
//freopen("zheng.txt","w",stdout);
int t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}
337

被折叠的 条评论
为什么被折叠?



