CF911G Mass Change Queries (线段树区间 合并)

Posted 昵称很长很长真是太好了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF911G Mass Change Queries (线段树区间 合并)相关的知识,希望对你有一定的参考价值。

题意:
给出一个数列,有q个操作,每种操作是把区间[l,r]中等于x的数改成y.输出q步操作完的数列.
题解:
100个数,很容易想到要从这里进行突破,对于某次操作我们只需要把这个区间的数x给移动到y的这个数的集合里面不就可以了。线段树合并!
这样的话我们对于每一种颜色动态开一个线段树,合并就把颜色为x的线段树区间l r合并到颜色为y的线段树的区间l r 上即可。
之前大多数的线段树合并是整颗线段树进行合并,这个是针对于某段区间进行合并,我们需要稍微调整一下这个update即可。
最后只需要遍历一遍这100棵线段树然后把有值的位置存到ans数组里面最后输出即可。
代码:

//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
//#define int long long
const int maxn=2e7+10;
#define endl '\\n'


int rt[110];
int ls[maxn],rs[maxn];
int cnt;
//bool tree[maxn];

void ins(int &node,int start,int ends,int pos){
    if(!node) node=++cnt;
    if(start==ends){
        //tree[node]=true;
        return ;
    }
    int mid=(start+ends)/2;
    if(pos<=mid) ins(ls[node],start,mid,pos);
    else ins(rs[node],mid+1,ends,pos);
    //push(node);
}

int mer(int x,int y){
    if(!x||!y) return x+y;
    ls[x]=mer(ls[x],ls[y]);
    rs[x]=mer(rs[x],rs[y]);
    return x;
}

void update(int &x,int &y,int start,int ends,int l,int r){  //y合并到x
    if(!y) return ;
    if(l<=start&&ends<=r){
        x=mer(x,y);y=0;
        return ;
    }
    if(!x) x=++cnt;   //x如果没有需要开辟新的结点
    int mid=(start+ends)/2;
    if(l<=mid) update(ls[x],ls[y],start,mid,l,r);
    if(mid<r) update(rs[x],rs[y],mid+1,ends,l,r);


}
int ans[200010];
void query(int node,int start,int ends,int val){
    if(node==0) return ;
    if(start==ends){
        ans[start]=val;
        return ;
    }
    int mid=(start+ends)/2;
    query(ls[node],start,mid,val);
    query(rs[node],mid+1,ends,val);
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        ins(rt[x],1,200000,i);
    }
    int q;
    cin>>q;
    while(q--){
        int l,r,x,y;
        cin>>l>>r>>x>>y;
        if(x==y) continue;
        update(rt[y],rt[x],1,200000,l,r);
    }
    for(int i=1;i<=100;i++){
        query(rt[i],1,200000,i);
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";



}

以上是关于CF911G Mass Change Queries (线段树区间 合并)的主要内容,如果未能解决你的问题,请参考以下文章

Mass Change Queries Codeforces - 911G

Mass Change Queries CodeForces - 911G (线段树合并)

Codeforces911 G. Mass Change Queries(分块,时间换空间技巧)

Codeforces911 G. Mass Change Queries(分块,时间换空间技巧)

题解CF1256A Payment Without Change

CF1279F New Year and Handle Change 题解