ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf1701 F. Points

2022-07-14 13:05:03  阅读:221  来源: 互联网

标签:lzy cnt int max sum Points query cf1701


题意:

定义美丽三元组 \(<i,j,k>\):\(i<j<k\) 且 \(k-i\le d\)

给定 \(d\),动态维护一个点集,支持添加点和删除点操作,在每次操作后输出全集中美丽三元组的数量

范围都是 \(2e5\)

思路:

\(f_i\) 表示点 \(i\) 存在的情况下,\([i+1,i+d]\) 中有多少个点。那么答案就是 \(\sum C_{f_i}^2=\frac{f_i(f_i-1)}{2}\)

考虑添加一个点 \(i\) 有啥影响:首先答案要加上 \(f_i(f_i-1)/2\)(\(f_i\) 是修改前的值);然后 \([i-d,i-1]\) 里的每个点 \(j\) 的 \(f\) 值加1,答案增加 \(\frac{(f_j+1)f_j}2-\frac{f_j(f_j-1)}2=f_j\)。所以答案要增加一个 \(f_j\) (修改前的)的区间和

删除点同理。但要注意操作顺序: \(f_i\) 是修改前的;然后答案变化 \(\frac{(f_j-1)(f_j-2)}2-\frac{f_j(f_j-1)}2=-(f_j-1)\) 所以是修改后的值

写一个支持区间修改、区间查询的线段树即可。还要维护每个点是否存在

const signed N = 100 + 2e5;

#define mid (l+r)/2
#define lson u*2
#define rson u*2+1
#define ls lson,l,mid
#define rs rson,mid+1,r

ll sum[N*4], cnt[N*4], lzy[N*4];

void pushup(int u) {
    sum[u] = sum[lson] + sum[rson];
    cnt[u] = cnt[lson] + cnt[rson];
}
void pushdn(int u) {
    if(lzy[u]) {
        sum[lson] += lzy[u] * cnt[lson], lzy[lson] += lzy[u];
        sum[rson] += lzy[u] * cnt[rson], lzy[rson] += lzy[u];
        lzy[u] = 0;
    }
}
void modi(int u, int l, int r, int x, int v, int w) { //单点修改存在性
    if(l == r) {
        cnt[u] = v, sum[u] = w; //记得把sum也清零
        return;
    }
    pushdn(u);
    if(x <= mid) modi(ls, x, v, w);
    else modi(rs, x, v, w);
    pushup(u);
}
void add(int u, int l, int r, int x, int y, int d) { //区间加,sum[]
    if(x <= l && r <= y) {
        sum[u] += cnt[u] * d, lzy[u] += d;
        return;
    }
    pushdn(u);
    if(x <= mid) add(ls, x, y, d);
    if(y > mid) add(rs, x, y, d);
    pushup(u);
}
ll query(int u, int l, int r, int x, int y, ll *arr) {
    if(x <= l && r <= y) return arr[u];
    if(y < l || x > r) return 0;
    pushdn(u);
    ll ans = 0;
    if(x <= mid) ans += query(ls, x, y, arr);
    if(y > mid) ans += query(rs, x, y, arr);
    return ans;
}

void sol() {
    int n=2e5, q, d; cin >> q >> d;
    ll ans = 0;
    while(q--) {
        int i; cin >> i;
        if(query(1,1,n, i, i, cnt)) { //已存在,要删除点
            ll t = query(1,1,n, min(n,i+1), min(n,i+d), cnt);
            add(1,1,n, max(1,i-d), max(1,i-1), -1);
            modi(1,1,n, i, 0, 0);
            ans -= t*(t-1)/2 + query(1,1,n, max(1,i-d), max(1,i-1), sum);
        }
        else { //添加点
            ll t = query(1,1,n, min(n,i+1), min(n,i+d), cnt);
            ans += t*(t-1)/2 + query(1,1,n, max(1,i-d), max(1,i-1), sum);
            add(1,1,n, max(1,i-d), max(1,i-1), 1); //这里取max可能会改到i
            modi(1,1,n, i, 1, t); //所以先区间加再修改比较稳妥
        }
        cout << ans << endl;
    }
}

标签:lzy,cnt,int,max,sum,Points,query,cf1701
来源: https://www.cnblogs.com/wushansinger/p/16477286.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有