1. 程式人生 > 其它 >luogu P7416 [USACO21FEB] No Time to Dry P

luogu P7416 [USACO21FEB] No Time to Dry P

https://www.luogu.com.cn/problem/P7416

對於每個數,記\(lst[i]\)表示上一個和\(i\)顏色相同的位置

如果\(lst[i]<l\)顯然\(ans+1\)

如果\(min(lst[i],i)<a[i]\)那麼\(ans+1\)(把\(lst[i]\)設為\(0\)即可)

然後就變成了詢問區間\(lst[i]<l\)的個數

拿主席樹維護一下即可

不對啊,可以離線,直接樹狀陣列即可
我是sg
code:

#include<bits/stdc++.h>
#define N 400050
using namespace std;
#define ls (a[rt].l)
#define rs (a[rt].r)
struct A {
    int l, r, s;
} a[N << 5];
void update(int rt) {
    a[rt].s = a[ls].s + a[rs].s;
}
int tot;
void add(int &rt, int lrt, int l, int r, int x, int o) {
    rt = ++ tot; a[rt] = a[lrt];
    if(l == r) {
        a[rt].s += o;
        return ;
    }
    int mid = (l + r) >> 1;
    if(x <= mid) add(ls, a[lrt].l, l, mid, x, o);
    else add(rs, a[lrt].r, mid + 1, r, x, o);
    update(rt);
}
int query(int rt, int l, int r, int L, int R) {
    if(!rt) return 0;
    if(L <= l && r <= R) return a[rt].s;
    int mid = (l + r) >> 1, ret = 0;
    if(L <= mid) ret = query(ls, l, mid, L, R);
    if(R > mid) ret += query(rs, mid + 1, r, L, R);
    return ret;
}
int mi[N][21];
int get(int l, int r) {
    int k = log2(r - l + 1);
    return min(mi[l][k], mi[r - (1 << k) + 1][k]);
}
int n, m, aa[N], lst[N], root[N];
map<int, int> mp;
int main() {
    // freopen("a.in","r",stdin);
    // freopen("a.out","w",stdout);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) scanf("%d", &aa[i]), lst[i] = mp[aa[i]], mp[aa[i]] = i, mi[i][0] = aa[i];
    for(int j = 1; j <= 19; j ++)
        for(int i = 1; i + (1 << j) - 1 <= n; i ++) 
            mi[i][j] = min(mi[i][j - 1], mi[i + (1 << (j - 1))][j - 1]);
    
    for(int i = 1; i <= n; i ++) 
        if(get(lst[i] + 1, i) < aa[i]) lst[i] = 0;
    
   // for(int i = 1; i <= n; i ++) printf("%d ", lst[i]); printf("\n");
    for(int i = 1; i <= n; i ++) add(root[i], root[i - 1], 0, n, lst[i], 1);
 //   for(int i = 1; i <= n; i ++) printf("%d ", root[i]); printf("    %d\n", n);
    while(m --) {
        int l, r;
        scanf("%d%d", &l, &r);
     //   printf("%d    %d    ", query(root[r], 0, n, 0, l - 1), query(root[l - 1], 0, n, 0, l - 1));
        printf("%d\n", query(root[r], 0, n, 0, l - 1) - query(root[l - 1], 0, n, 0, l - 1));
    }
    return 0;
}