题意:
一个剧一共有n季,每季有ai集。问有多少对x,y(x≠y),使得第x季有第y集且第y季有第x集。
题解:
问题可以转换成对于当前第i个数,区间1~min(a[i], i-1) 有多少个数大于i的,转换成主席树求解。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 7;
struct node
{
int lc, rc, v;
}t[4200000];
int rt[maxn], a[maxn], tot;
typedef long long ll;
int build(int l, int r)
{
int now = ++tot;
t[now].lc = t[now].rc = t[now].v = 0;
if(l == r) return now;
int mid = (l + r) >> 1;
t[now].lc = build(l, mid);
t[now].rc = build(mid+1, r);
return now;
}
int update(int last, int l, int r, int pos)
{
int now = ++tot;
t[now] = t[last];
t[now].v ++;
if(l == r) return now;
int mid = (l + r) >> 1;
if(pos <= mid) t[now].lc = update(t[last].lc, l, mid, pos);
else t[now].rc = update(t[last].rc, mid+1, r, pos);
return now;
}
int query(int c, int L, int R, int l, int r)
{
if(L <= l && r <= R) return t[c].v;
int mid = (l + r) >> 1;
int res = 0;
if(L <= mid) res += query(t[c].lc, L, R, l, mid);
if(R > mid) res += query(t[c].rc, L, R, mid+1, r);
return res;
}
int main()
{
int n; scanf("%d", &n);
// printf("%d\n",n*(int)log2(n));
rt[0] = build(1, n);
for(int i = 1;i <= n;i ++) {
scanf("%d", &a[i]);
a[i] = min(a[i], n);
rt[i] = update(rt[i-1], 1, n, a[i]);
}
ll res = 0;
for(int i = 2;i <= n;i ++) {
res += query(rt[ min(i-1, a[i]) ], i, n, 1, n);
// printf("%lld\n", res);
}
printf("%lld\n", res);
return 0;
}