zoukankan      html  css  js  c++  java
  • Mass Change Queries Codeforces

    https://codeforces.com/contest/911/problem/G

    没想到线段树合并还能这么搞。。

    对每个权值建一个线段树(动态开点),如果权值为k的线段树上第i位为1,那么表示a[i]=k;如果权值为k的线段树上第i位为0,表示a[i]≠k

    改变权值的时候,就是把[l,r]分解成多个线段树上的区间;对于每个分解出的区间,分别在权值为x的线段树上和权值为y的线段树上找到对应的节点,设某个区间找到的节点为a,b,则把b子树合并到a上

    注意!要特判x==y时跳过操作

    最后枚举一遍所有权值得到答案

    复杂度n*100+n*log

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 #define fi first
     8 #define se second
     9 #define mp make_pair
    10 #define pb push_back
    11 typedef long long ll;
    12 typedef unsigned long long ull;
    13 typedef pair<int,int> pii;
    14 namespace S
    15 {
    16 #define N 4000000
    17 int d[N],lc[N],rc[N];
    18 queue<int> q;
    19 void init()
    20 {
    21     for(int i=1;i<N;i++)    q.push(i);
    22 }
    23 int getnode()
    24 {
    25     int t=q.front();q.pop();
    26     lc[t]=rc[t]=d[t]=0;
    27     return t;
    28 }
    29 void delnode(int x){q.push(x);}
    30 void addx(int L,int x,int l,int r,int &num)
    31 {
    32     if(!num)    num=getnode();
    33     if(l==r)    {d[num]+=x;return;}
    34     int mid=l+((r-l)>>1);
    35     if(L<=mid)    addx(L,x,l,mid,lc[num]);
    36     else    addx(L,x,mid+1,r,rc[num]);
    37 }
    38 int merge(int x,int y)
    39 {
    40     if(!x||!y)    return x+y;
    41     lc[x]=merge(lc[x],lc[y]);
    42     rc[x]=merge(rc[x],rc[y]);
    43     d[x]+=d[y];
    44     delnode(y);
    45     return x;
    46 }
    47 void work(int L,int R,int l,int r,int &n1,int &n2)
    48 {
    49     if(!n1)    n1=getnode();
    50     if(L<=l&&r<=R)    {n1=merge(n1,n2);n2=0;return;}
    51     int mid=l+((r-l)>>1);
    52     if(L<=mid)    work(L,R,l,mid,lc[n1],lc[n2]);
    53     if(mid<R)    work(L,R,mid+1,r,rc[n1],rc[n2]);
    54 }
    55 int ans[201000];
    56 void dfs(int l,int r,int k,int num)
    57 {
    58     if(l==r)
    59     {
    60         if(d[num])    ans[l]=k;
    61         return;
    62     }
    63     int mid=l+((r-l)>>1);
    64     dfs(l,mid,k,lc[num]);dfs(mid+1,r,k,rc[num]);
    65 }
    66 }
    67 int rt[101];
    68 int n;
    69 int main()
    70 {
    71     int t,i,l,r,x,y,q;
    72     S::init();
    73     scanf("%d",&n);
    74     for(i=1;i<=n;i++)
    75     {
    76         scanf("%d",&t);
    77         S::addx(i,1,1,n,rt[t]);
    78     }
    79     scanf("%d",&q);
    80     while(q--)
    81     {
    82         scanf("%d%d%d%d",&l,&r,&x,&y);
    83         if(x==y)    continue;
    84         S::work(l,r,1,n,rt[y],rt[x]);
    85     }
    86     for(i=1;i<=100;i++)    S::dfs(1,n,i,rt[i]);
    87     for(i=1;i<=n;i++)    printf("%d ",S::ans[i]);
    88     return 0;
    89 }

    (分块也能做,不过我自己写的常数太糟...开了Ofast交了几十发后也只A了一次。。。)

  • 相关阅读:
    添加coreseek中文分词
    linux 常用处理命令
    rewrite nginx
    判断浏览器类型
    Cookie 读写类
    Php 异常处理 exception
    C++实验:时间和日期类
    数据结构:删除链表元素
    数据结构-循环单链表
    TOJ-5395 大于中值的边界元素
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9395434.html
Copyright © 2011-2022 走看看