[JXOI2017] Color

\ (Orz \) everybody solution to a problem chiefs, I come out of worship

There really did not understand monotonous stack

Method a: stack segment tree +

First, the number of discussion topics range, we can think of to enumerate an endpoint \ (r \) , to find all of \ (l \)

We wish to set: \ (ml [i] \) is the i-th minimum position colors appear, \ (mr [i] \) is the maximum position of the first occurrence of the i

We think the right end for a point, he has those values ​​can not be selected:

Suppose there is a color \ (of Mr \) value is smaller than the right end point of the current enumeration, the \ ([ml, mr] \ ) all the points inside the left end are not selected, the corresponding line segment tree is assigned to the interval 0

Suppose there is a color, the right end in the current enumeration \ ([ml [i], mr [i]] \) between, then we record a \ (Last [I] \) , the right end point of the current means less than the largest i

Then \ ([1, last [i ]] \) All values can not be selected

Then we have to find one of the biggest last, with a heap to

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define int long long
il int read() {
    re int x = 0, f = 1; re char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
    return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define mem(k, p) memset(k, p, sizeof(k))
#define ls k * 2
#define rs k * 2 + 1
#define maxn 300005
int n, m, a[maxn], last[maxn], ans, ml[maxn], mr[maxn], tag[maxn << 2], sum[maxn << 2];
struct node {int id, val; il bool operator < (const node&x) const{return val < x.val;}};
priority_queue<node> q;
il void pushdown(int k, int l, int r, int mid) {
    if(tag[k] == -1) return;
    sum[ls] = (mid - l + 1) * tag[k], sum[rs] = (r - mid) * tag[k];
    tag[ls] = tag[rs] = tag[k]; tag[k] = -1;
}
il void modify(int k, int l, int r, int ll, int rr, int x) {
    if(l > rr || ll > r) return;
    if(ll <= l && r <= rr) return (void)(tag[k] = x, sum[k] = (r - l + 1) * x);
    int mid = (l + r) >> 1; pushdown(k, l, r, mid);
    modify(ls, l, mid, ll, rr, x), modify(rs, mid + 1, r, ll, rr, x);
    sum[k] = sum[ls] + sum[rs];
}
il int query(int k, int l, int r, int ll, int rr) {
    if(l > rr || ll > r) return 0;
    if(ll <= l && r <= rr) return sum[k];
    int mid = (l + r) >> 1; pushdown(k, l, r, mid);
    return query(ls, l, mid, ll, rr) + query(rs, mid + 1, r, ll, rr);
}
il void solve() {
    n = read(), ans = 0, mem(tag, -1), modify(1, 1, n, 1, n, 1);
    while(!q.empty()) q.pop();
    rep(i, 1, n) ml[i] = n + 1, mr[i] = last[i] = 0;
    rep(i, 1, n) a[i] = read(), ml[a[i]] = min(ml[a[i]], i), mr[a[i]] = max(mr[a[i]], i);
    rep(i, 1, n) {
        last[a[i]] = i, q.push((node){a[i], last[a[i]]});
        if(i == mr[a[i]]) modify(1, 1, n, ml[a[i]] + 1, mr[a[i]], 0);
        while(!q.empty()) {
            int x = q.top().id;
            if(last[x] == mr[x]) q.pop();
            else break;
        }
        int pax = (q.empty() ? 1 : q.top().val + 1);
        ans += query(1, 1, n, pax, i);
    }
    printf("%lld\n", ans);
}
signed main() {
    int T = read();
    while(T --) solve();
    return 0;
}

Randomization

For each position, we need a random value, and then need to ensure that all of the exclusive OR result of random values of the same color as \ (0 \)

Since the XOR meet \ (A \\) ^ \ (\ b = 0 \) , so we put every color except the last one of all random values XOR up, so the last one is equal to the random value

Then we find that each meet the conditions for a zone, he's apparently different values ​​or equal to 0

So the question becomes transformed: the number of intervals or different and equal to 0

Due to the exclusive nature or above, so we just use \ (map \) save what you can

It is now @ \ (Ebola \) prove chiefs, our error rate is very small.

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define debug printf("Now is Line : %d\n",__LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define int long long
il int read() {
    re int x = 0, f = 1; re char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
    return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define drep(i, s, t) for(re int i = t; i >= s; -- i)
#define Next(i, u) for(re int i = head[u]; i; i = e[i].next)
#define mem(k, p) memset(k, p, sizeof(k))
#define lb(x) (x)&(-(x))
#define ls k * 2
#define rs k * 2 + 1
#define maxn 300005
int n, m, a[maxn], val[maxn];
vector<int>q[maxn];
map<int, int> p;
il int Random() {
    return 1ll * rand() * rand() * rand();
}
signed main() {
    srand(time(0));
    int T = read();
    while(T --) {
        n = read();
        rep(i, 1, n) a[i] = read(), q[a[i]].push_back(i), val[i] = 0;
        rep(i, 1, n) {
            int sum = 0;
            for(re int j = 0; j < q[i].size(); ++ j) {
                if(j == q[i].size() - 1) val[q[i][j]] = sum;
                else sum ^= (val[q[i][j]] = Random());
            }
            q[i].clear();
        }
        int ans = 0, now = 0; p[0] = 1;
        rep(i, 1, n) now ^= val[i], ans += p[now], ++ p[now];
        rep(i, 1, n) now ^= val[i], p[now] = 0;
        printf("%lld\n", ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/bcoier/p/11618348.html