杭电多校第三场 game 带修莫队

先来一道简单的普通莫队
洛谷HH的项链

// luogu-judger-enable-o2
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<bitset>
#include<algorithm>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr_0(a) memset(a, 0, sizeof(a))
#define clr_INF(a) memset(a, INF, sizeof(a))
#define lowbit(x) x & -x
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define PB push_back
#define POP pop_back
const double pi = acos(-1);
const int maxn = 1e6 + 10;
const int maxm = 50011;
const ll mod = 998244353;
const int hash_mod = 19260817;
int n, m, block, ans;
int a[maxn], cnt[maxn], Ans[maxn], bl[maxn];
struct node{
    int l, r, id;
}b[maxn];
bool cmp(node a, node b){
    return bl[a.l]^bl[b.l]?a.l<b.l:((bl[a.l]&1)?a.r<b.r:a.r>b.r);
}
void del(int x){
    cnt[a[x]] --;
    if(cnt[a[x]]==0) ans --;
}
void add(int x){
    if(cnt[a[x]]==0) ans ++;
    cnt[a[x]] ++;
}
int read()
{
    char x;
    while((x = getchar()) > '9' || x < '0') ;
    int u = x - '0';
    while((x = getchar()) <= '9' && x >= '0') u = (u << 3) + (u << 1) + x - '0';
    return u;
}
int main()
{
    scanf("%d", &n);
    block = n / sqrt(n);
    for(int i = 1 ; i <= n ; ++ i){
        a[i] = read();
        bl[i] = (i - 1) / block + 1;
    }
    scanf("%d", &m);

    for(int i = 1 ; i <= m ; ++ i){
        b[i].l = read(); b[i].r = read();
        b[i].id = i;
    }

    //cout << block << endl;
    sort(b + 1, b + 1 + m, cmp);//puts("777");
    int l = 0, r = 0;
    for(int i = 1 ; i <= m ; ++ i){
        int ql = b[i].l, qr = b[i].r;
        while(l < ql) del(l ++);
        while(l > ql) add(-- l);
        while(r < qr) add(++ r);
        while(r > qr) del(r --);
        Ans[b[i].id] = ans;
    }
    for(int i = 1 ; i <= m ; ++ i) cout << Ans[i] <<endl;
    return 0;
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<bitset>
#include<algorithm>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr_0(a) memset(a, 0, sizeof(a))
#define clr_INF(a) memset(a, INF, sizeof(a))
#define lowbit(x) x & -x
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define PB push_back
#define POP pop_back
const double pi = acos(-1);
const int maxn = 1e5 + 10;
const int maxm = (1<<21) + 5;
const ll mod = 998244353;
const int hash_mod = 19260817;
int n, m, l, r, t, qcnt, tcnt, op, x, block;
int bl[maxn], a[maxn], p[maxn];
ll Ans[maxn], cnt[maxm], sum[maxn];
ll ans;
struct node{
    int l, r, t, id;
}q[maxn];
bool cmp(node a, node b){
    if(bl[a.l] != bl[b.l]) return a.l < b.l;
    if(bl[a.r] != bl[b.r]) return a.r < b.r;
    return a.t < b.t;
}
void add(int x){ans += cnt[sum[x]] ++;}
void del(int x){ans -= -- cnt[sum[x]];}
void upd(int i, int t){
    //cout << ans << endl;
    if(q[i].l <= p[t] && p[t] <= q[i].r) del(p[t]);
    sum[p[t]] ^= a[p[t]];
    swap(a[p[t]], a[p[t] + 1]);
    sum[p[t]] ^= a[p[t]];

    if (q[i].l <= p[t] && p[t] <= q[i].r) add(p[t]);
}
int main()
{
    while(~scanf("%d %d", &n, &m)){
        clr_0(cnt);

        block = max(10, (int)pow(n, 2.0 / 3));
        for(int i = 1 ; i <= n ; ++ i){
            scanf("%d", &a[i]);
            sum[i] = sum[i-1] ^ a[i];
            bl[i] = (i - 1) / block + 1;
        }
        qcnt = tcnt = 0;
        for(int i = 1 ; i <= m ; ++ i){
            scanf("%d", &op);
            if(op == 1){
                scanf("%d %d", &l, &r);
                q[++qcnt] = {l-1, r, tcnt, qcnt};
            }
            else{
                scanf("%d", &x);
                p[++tcnt] = x;
            }
        }
        sort(q + 1, q + 1 + qcnt, cmp);
        l = 0, r = -1, t = 0; ans = 0;
        for(int i = 1 ; i <= qcnt ; ++ i){
            int ql = q[i].l, qr = q[i].r, qt = q[i].t;
            while(l < ql) del(l ++);
            while(l > ql) add(-- l);

            while(r < qr) add(++ r);
            while(r > qr) del(r --);
            while(t < qt) upd(i, ++ t);
            while(t > qt) upd(i, t --);

            Ans[q[i].id] = 1LL * (r - l + 1) * (r - l) / 2 - ans;
        }
        for(int i = 1 ; i <= qcnt ; ++ i) cout << Ans[i] << endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值