《河南省赛C》

时间:2021-05-30
本文章向大家介绍《河南省赛C》,主要包括《河南省赛C》使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

https://ac.nowcoder.com/acm/contest/17148/C。

这题挺好的。

其实一开始已经差不多想到了。

前缀和+容斥。

但是这个容斥一直没想到怎么做,就硬冲线段树去了。

这里其实有一个很重要的信息。

假设L点的右边有解的位置是r。

那么对于所有L左边的点,他们的有解位置肯定<=r。

那么我们查询的时候。

对于区间[L,r]:先找到r的左有解位置pos.

那么对于[L,pos]里的点,他们的右有解位置肯定<=r。

那么我们把以他们为开头~n里的所有值加上(这里用前缀和来处理即可),然后再 - (pos - L + 1) * (n - r)即可。

因为这个信息的存在,我们减去的区间里的右有解位置都肯定<=r。不会存在减去负的情况,也满足正确性。

对于sum[i]表示以i ~ n里面满足条件的序列数。

我们先尺取维护出L[i] - i的最大左有解点,r[i] - i的最小有解点。

那么sum[i]就可以走一遍前缀和取出来。

这里还有个小坑。

如果下面异或处理的L和赋值的一样,那么在第一个L异或之后,L就变了。

所以要用不同的变量。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> pii;
const int N = 1e6 + 5;
const int M = 1e5 + 5;
const LL Mod = 998244353;
#define pi acos(-1)
#define INF 1e18
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

int n,m,k,a[N],lp[N],rp[N];
LL sum[N];
deque<int> Q;
map<int,int> mp;
LL solve(int L,int r) {
    int pos = lp[r];
    if(pos < L) return 0;
    LL ma = sum[L] - sum[pos + 1];
    return ma - 1LL * (pos - L + 1) * (n - r);
}
int main() {
    n = read(),m = read(),k = read();
    for(int i = 1;i <= n;++i) a[i] = read();
    int now = 0,cnt = 0;
    while(now <= n) {
        if(cnt < k) {
            if(now == n) break;
            int pre = 0;
            if(Q.size() > 0) pre = Q.back();
            Q.push_back(++now);
            mp[a[now]]++;
            if(mp[a[now]] == 1) {
                cnt++;
                if(cnt == k && Q.size() > 0) {
                    rp[Q.front()] = Q.back();
                    lp[Q.back()] = Q.front();
                }
            }
            else if(Q.size() > 0){
                lp[Q.back()] = lp[pre];
            }
        }
        else {
            int x = Q.front();
            Q.pop_front();
            mp[a[x]]--;
            if(mp[a[x]] == 0) cnt--;
            if(cnt == k && Q.size() > 0) {
                rp[Q.front()] = Q.back();
                lp[Q.back()] = Q.front();
            }
        }
    }
    for(int i = 1;i <= n;++i) {
        if(a[i] == a[i - 1]) {
            rp[i] = rp[i - 1];
            lp[i] = lp[i - 1];
        }
    }
    for(int i = n;i >= 1;--i) {
        sum[i] = sum[i + 1];
        if(rp[i] != 0) sum[i] += 1LL * (n - rp[i] + 1);
    }
 //   for(int i = 1;i <= n;++i) printf("L[%d] is %d r[%d] is %d sum[%d] is %lld\n",i,lp[i],i,rp[i],i,sum[i]);
    LL ans = 0;
    while(m--) {
        int LL,rr;LL = read(),rr = read();
        int L = min(LL ^ ans,rr ^ ans) + 1;
        int r = max(LL ^ ans,rr ^ ans) + 1;
        ans = solve(L,r);
        printf("%lld\n",ans);
    }

    system("pause");
    return 0;
}
/*
10 5 3
1 2 3 4 5 6 7 8 9 10
1 5
2 6
3 7
1 5

*/
View Code

原文地址:https://www.cnblogs.com/zwjzwj/p/14828970.html