标签:for public 不同 clu 条件 变形 add else close
区间符合条件的充要条件是\(Max-Min+1=Cnt\)其中\(Max,Min,Cnt\)分别为区间最大值,最小值,不同的数的个数。
变形后得\(Max-Min-Cnt+1=0\)
考虑枚举右端点,在线段树上维护左端点\(Max-Min-Cnt+1\)的最小值。
\(Min,Max\)可以用单调栈维护,记\(last_i\)为\(a_i\)上一次出现的位置,那么对于每个左端点\(i\),\([last_i+1, i]\)的\(Cnt\)均\(+1\)
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=100000;
class Ele {
public:
int v, id;
static bool cmp(Ele &a, Ele &b) {
return a.v<b.v || (a.v==b.v && a.id<=b.id);
}
};
void getLast(int n, int a[], int last[]) {
static Ele b[maxn+1];
for (int i=1; i<=n; i++) {
b[i].v = a[i], b[i].id = i;
}
sort(b+1, b+n+1, Ele::cmp);
for (int i=1; i<=n; i++) {
last[b[i].id] = b[i].v==b[i-1].v ? b[i-1].id : 0;
}
}
class SegmentTree {
public:
int v[4*maxn+1], cnt[4*maxn+1], mark[4*maxn+1];
void init(int o, int l, int r) {
int mid=(l+r)/2;
cnt[o] = r-l+1;
if (l!=r) init(o*2, l, mid), init(o*2+1, mid+1, r);
}
void pushDown(int o, int l, int r) {
if (mark[o]) {
v[o] += mark[o];
if (l!=r) {
mark[o*2]+=mark[o];
mark[o*2+1]+=mark[o];
}
mark[o] = 0;
}
}
void add(int o, int l, int r, int tl, int tr, int tv) {
pushDown(o, l, r);
if (l==tl && r==tr) {
mark[o] += tv;
pushDown(o, l, r);
} else {
int mid=(l+r)/2;
if (tl<=mid) add(o*2, l, mid, tl, min(tr, mid), tv);
else pushDown(o*2, l, mid);
if (tr>mid) add(o*2+1, mid+1, r, max(tl, mid+1), tr, tv);
else pushDown(o*2+1, mid+1, r);
if (v[o*2]<v[o*2+1]) v[o]=v[o*2], cnt[o]=cnt[o*2];
else if (v[o*2]>v[o*2+1]) v[o]=v[o*2+1], cnt[o]=cnt[o*2+1];
else v[o]=v[o*2], cnt[o]=cnt[o*2]+cnt[o*2+1];
}
}
int getZero(int o, int l, int r, int tl, int tr) {
pushDown(o, l, r);
if (l==tl && r==tr) return v[o] ? 0 : cnt[o];
else {
int mid=(l+r)/2, ret=0;
if (tl<=mid) ret+=getZero(o*2, l, mid, tl, min(tr, mid));
if (tr>mid) ret+=getZero(o*2+1, mid+1, r, max(tl, mid+1), tr);
return ret;
}
}
};
int main() {
freopen("easy.in", "r", stdin);
freopen("easy.out", "w", stdout);
static int a[maxn+1], last[maxn+1], minq[maxn+1], maxq[maxn+1];
int n;
scanf("%d", &n);
for (int i=1; i<=n; i++) {
scanf("%d", a+i);
}
getLast(n, a, last);
static SegmentTree sgt;
sgt.init(1, 1, n);
long long ans=0;
for (int i=1; i<=n; i++) {
if (last[i]<i-1) sgt.add(1, 1, n, last[i]+1, i-1, -1);
for (; minq[0] && a[minq[minq[0]]]>=a[i]; minq[0]--) {
sgt.add(1, 1, n, (minq[0]==1 ? 1 : minq[minq[0]-1]+1), minq[minq[0]], a[minq[minq[0]]]);
}
sgt.add(1, 1, n, minq[0] ? minq[minq[0]]+1 : 1, i, -a[i]);
minq[++minq[0]] = i;
for (; maxq[0] && a[maxq[maxq[0]]]<=a[i]; maxq[0]--) {
sgt.add(1, 1, n, (maxq[0]==1 ? 1 : maxq[maxq[0]-1]+1), maxq[maxq[0]], -a[maxq[maxq[0]]]);
}
sgt.add(1, 1, n, maxq[0] ? maxq[maxq[0]]+1 : 1, i, a[i]);
maxq[++maxq[0]] = i;
ans += sgt.getZero(1, 1, n, 1, i);
}
printf("%lld\n", ans);
fclose(stdin);
fclose(stdout);
return 0;
}
标签:for public 不同 clu 条件 变形 add else close
原文地址:https://www.cnblogs.com/BunnyLutts/p/13909782.html