题解:P13536 [IOI 2025] 神话三峰(triples)(Part 1)
IvanZhang2009 · · 题解
我只会第一问。
考虑三峰
如果最高峰是
如果最高峰是
如果最高峰是
最难的是
把充要条件写成这样:
移项:
直接枚举
注意到
#include "triples.h"
#include<bits/stdc++.h>
using namespace std;
#define MOD 998244353
#define ll long long
#define pii pair<int,int>
#define all(v) v.begin(),v.end()
#define pb push_back
#define REP(i,b,e) for(int i=(b);i<(int)(e);++i)
#define over(x) {cout<<(x)<<endl;return;}
#define lowbit(x) ((x)&(-(x)))
#define cntbit(x) __builtin_popcount(x)
#define deal(v) sort(all(v));v.erase(unique(v.begin(),v.end()),v.end())
#define lbound(v,x) lower_bound(all(v),x)-v.begin()
vector<int>b[200005];
int cnt[400005];
long long count_triples(vector<int>a) {
int n=a.size();
ll ans=0;
REP(i,0,n)if(i+a[i]<n){
int j=i+a[i];
if(a[j]>a[i])continue;
if(a[i+a[j]]+a[j]==a[i])++ans;
if(i+a[j]!=j-a[j]&&a[j-a[j]]+a[j]==a[i])++ans;
}
REP(i,0,n)if(i>=a[i]){
int j=i-a[i];
if(a[j]>a[i])continue;
if(a[i-a[j]]+a[j]==a[i])++ans;
if(i-a[j]!=j+a[j]&&a[j+a[j]]+a[j]==a[i])++ans;
}
REP(i,0,n)if(i+a[i]<n){
int j=i+a[i];
if(a[j]>a[i]&&i+a[j]<n){
if(a[i+a[j]]==a[j]-a[i]&&a[i+a[j]]!=a[i])++ans;
}
}
vector<int>T;
REP(i,0,n)T.pb(i-a[i]);
deal(T);
REP(i,0,n)b[lbound(T,i-a[i])].pb(i);
int B=sqrt(n);
REP(_,0,T.size()){
if(b[_].size()<=B){
REP(i,0,b[_].size()){
REP(j,i+1,b[_].size()){
int I=b[_][i],J=b[_][j];
if(J+a[I]<n&&a[J+a[I]]==J-I)++ans;
}
}
}else{
for(auto i:b[_])++cnt[i+a[i]];
REP(i,0,n)if(i-a[i]>=0){
ans+=cnt[i-a[i]]*cnt[i+a[i]];
}
for(auto i:b[_])--cnt[i+a[i]];
}
}
// REP(i,0,n){
// REP(j,i+1,n)if(i-a[i]==j-a[j]&&j+a[i]<n){
// if(a[j+a[i]]==j-i)++ans;
// }
// }
return ans;
}