题解 城市地平线
于是,只有我不会 T1 的世界诞生了
一个区间合法的条件是左右端点是区间前 \(k\) 大
容易做到 \(O(n^2\log n)\),但然后就不会了,甚至在笛卡尔树上折腾了半天下不来
枚举作为前 k 大的端点是不便于计算的
那么枚举第 \(k\) 大的位置,则所有比这个数大的位置都是可行的端点
那么若比第 \(i\) 个数大的有 \(x\) 个,这个数是从左到右第 \(rk\) 个
则贡献为 \(\min(rk, k, x-rk+1, x-k+1)\)(这个数的左右各 k 个)
发现这个东西是关于 \(k\) 的分段函数
将两个系数分别差分维护即可
复杂度 \(O(n\log n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, l, r;
int h[N];
namespace force{
int sta[N], top;
bool calc(int i, int j, int k) {
top=0;
for (int l=i; l<=j; ++l) sta[++top]=h[l];
sort(sta+1, sta+top+1);
return lower_bound(sta+1, sta+top+1, h[i])-sta>=top-k+1 && lower_bound(sta+1, sta+top+1, h[j])-sta>=top-k+1;
}
int solve(int k) {
// cout<<"solve: "<<k<<endl;
int ans=0;
for (int i=1; i<=n; ++i)
for (int j=i+k-1; j<=n; ++j)
ans+=calc(i, j, k);
// cout<<ans<<endl;
return ans;
}
void solve() {
int ans=0;
for (int i=l; i<=r; ++i) ans^=solve(i);
cout<<ans<<endl;
}
}
namespace task1{
int ans[N], bit[N], sum;
inline void add(int i) {for (; i; i-=i&-i) ++bit[i];}
inline int query(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bit[i]; return ans;}
void solve() {
for (int i=1; i<=n; ++i) {
for (int j=1; j<=n; ++j) bit[j]=0;
for (int j=i; j<=n; ++j) {
add(h[j]);
// cout<<"ij: "<<i<<' '<<j<<' '<<max(query(h[i]), query(h[j]))<<endl;
++ans[max(query(h[i]), query(h[j]))];
--ans[j-i+2];
}
}
for (int i=1; i<=n; ++i) ans[i]+=ans[i-1];
// cout<<"ans: "; for (int i=1; i<=n; ++i) cout<<ans[i]<<' '; cout<<endl;
for (int i=l; i<=r; ++i) sum^=ans[i];
cout<<sum<<endl;
}
}
namespace task2{
int bit[N];
inline void add(int i) {for (; i; i-=i&-i) ++bit[i];}
inline void del(int i) {for (; i; i-=i&-i) --bit[i];}
inline int query(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bit[i]; return ans;}
int solve(int k) {
int ans=0;
for (int i=1; i+k-1<=n; ++i) {
for (int j=i; j<i+k-1; ++j) add(h[j]);
int j;
for (j=i+k-1; j<=n; ++j) {
add(h[j]);
if (query(h[i])>k) break;
if (query(h[j])<=k) ++ans;
}
while (j>=i) del(h[j--]);
}
return ans;
}
void solve() {
int ans=0;
for (int i=l; i<=r; ++i) ans^=solve(i);
cout<<ans<<endl;
}
}
namespace task3{
int bit[N];
ll ans[N], sum;
inline void add(int i) {for (; i; i-=i&-i) ++bit[i];}
inline int query(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bit[i]; return ans;}
void solve() {
for (int i=1; i<=n; ++i) {
add(h[i]);
int x=n-h[i]+1, rk=query(h[i]), t=min(rk, x-rk+1);
int pos=(x+1)>>1;
for (int k=l; k<=r; ++k) ans[k]+=max(0, min(min(rk, k), min(x-rk+1, x-k+1)));
}
for (int i=l; i<=r; ++i) sum^=ans[i];
cout<<sum<<endl;
}
}
namespace task{
int bit[N];
ll ans1[N], ans2[N], ans;
inline void add(int i) {for (; i; i-=i&-i) ++bit[i];}
inline int query(int i) {int ans=0; for (; i<=n; i+=i&-i) ans+=bit[i]; return ans;}
void solve() {
for (int i=1; i<=n; ++i) {
add(h[i]);
int x=n-h[i]+1, rk=query(h[i]), t=min(rk, x-rk+1);
int pos=(x+1)>>1;
if (t<=0) continue;
if (t<pos) {
++ans1[1], --ans1[t];
ans2[t]+=t, ans2[x+1-t+1]-=t;
--ans1[x+1-t+1], ans2[x+1-t+1]+=x+1;
++ans1[x+1], ans2[x+1]-=x+1;
}
else {
++ans1[1], --ans1[pos+1];
--ans1[pos+1], ans2[pos+1]+=x+1;
++ans1[x+1], ans2[x+1]-=x+1;
}
}
for (int i=1; i<=n; ++i) ans1[i]+=ans1[i-1], ans2[i]+=ans2[i-1];
for (int i=l; i<=r; ++i) ans^=ans1[i]*i+ans2[i];
cout<<ans<<endl;
}
}
signed main()
{
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
n=read(); l=read(); r=read();
for (int i=1; i<=n; ++i) h[i]=read();
// force::solve();
// if (n<=1000) task1::solve();
// else task2::solve();
task::solve();
return 0;
}