ICode9

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

xsy2517. color

2022-06-11 18:02:02  阅读:101  来源: 互联网

标签:xsy2517 return color ll tr int ans inline


有 \(n\) 种颜色,第 \(i\) 种颜色的美丽值为 \(a_i\)。给定一根长度为 \(n\) 的颜色序列。一段区间的美丽值定义为出现的颜色的美丽值之和,如果一种颜色出现了多次,也只被计算一次。\(q\) 次操作,要支持单点修改颜色和区间询问美丽值,数据在线。
\(1\le n,q\le 10^5\)。


小清新主席树题。

考虑对区间中出现多次的颜色在最先出现的位置计算它,那么最先出现的位置满足上一次出现该颜色的位置在询问左端点 \(l\) 的左侧。于是可以把第 \(i\) 个位置抽象成坐标系上的一个点 \((\text{last}_{\text{col}_i}+1,i)\),询问就是 \((1\sim l,l\sim r)\) 矩形的和。容易用树状数组套主席树实现。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
struct Node{int ls,rs;ll sum;}tr[N*100];
int n,m,cnt,c[N],w[N],rt[N];ll ans;set<int>s[N];
inline int lst(int c,int p){
    set<int>::iterator it=s[c].lower_bound(p);
    return *(--it);
}
inline int nxt(int c,int p){
    set<int>::iterator it=s[c].upper_bound(p);
    return it==s[c].end()?-1:*it;
}
inline void update(int &x,int l,int r,int y,int v){
    if(!x)x=++cnt;
    if(l==r)return void(tr[x].sum+=v);
    int mid=l+r>>1;
    y<=mid?update(tr[x].ls,l,mid,y,v):update(tr[x].rs,mid+1,r,y,v);
    tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum;
}
inline ll query(int x,int l,int r,int L,int R){
    if(L<=l&&R>=r)return tr[x].sum;
    int mid=l+r>>1;ll ans=0;
    if(L<=mid)ans=query(tr[x].ls,l,mid,L,R);
    if(R>mid)ans+=query(tr[x].rs,mid+1,r,L,R);
    return ans;
}
inline void add(int x,int y,int v){for(;x<=n;x+=x&-x)update(rt[x],1,n,y,v);}
inline ll ask(int x,int l,int r){ll ans=0;for(;x;x&=x-1)ans+=query(rt[x],1,n,l,r);return ans;}
inline void modify(int p,int o){
    int v=lst(c[p],p),u=nxt(c[p],p);
    add(v+1,p,-w[c[p]]);
    if(~u){
        add(p+1,u,-w[c[p]]);
        add(v+1,u,w[c[p]]);
    }
    s[c[p]].erase(p),c[p]=o;
    s[o].insert(p);
    v=lst(o,p),u=nxt(o,p);
    if(~u){
        add(v+1,u,-w[o]);
        add(p+1,u,w[o]);
    }
    add(v+1,p,w[o]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)scanf("%d",c+i),s[i].insert(0),s[c[i]].insert(i);
    for(int i=1;i<=n;++i)scanf("%d",w+i);
    for(int i=1;i<=n;++i)add(lst(c[i],i)+1,i,w[c[i]]);
    while(m--){
        int type;ll l,r;scanf("%d%lld%lld",&type,&l,&r);
        if(type&1)modify(l^ans,r^ans);
        else printf("%lld\n",ans=ask(l^ans,l^ans,r^ans));
    }
    return 0;
}

标签:xsy2517,return,color,ll,tr,int,ans,inline
来源: https://www.cnblogs.com/Samsara-soul/p/16366418.html

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

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

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

ICode9版权所有