zoukankan      html  css  js  c++  java
  • 【科技】带修改莫队

    阅前提示:

    拥有普通莫队的基础知识;理解莫队的思想;
     

    简介:

    莫队支持的是离线操作,普通莫队只支持查询操作;

    而带修改莫队还支持单点修改操作

    原理:

    普通莫队每一个询问有L,R,ID三个属性;因为只有查询操作,所以改变其查询顺序并不会影响算法的正确性;而加入单点修改后,就不能任意改变顺序,这会影响最终答案;带修改莫队的思路就是在查询中加一个属性TM,表示在原顺序中该查询之前离其最近的一个修改操作的ID;每次执行查询操作前都执行在它之前的修改,并将在它之后的修改操作中已执行的取消;这样就可以不改变原始的顺序了。

    实现:

    在存储修改操作时,使用前向星思想:PRE,COLOR,POS,分别表示前一个修改操作、该修改操作修改的颜色、操作的数;那遍历时只需依次向前即可;

    在下面的程序中将会看见

     for (int j = e[i - 1].tm + 1; j <= e[i].tm; ++j) 

      即可实现从上一个操作中可能没有被操作过的修改

     for (int j = e[i - 1].tm; j >= e[i].tm + 1; --j) 

      即可实现从上一个操作中可能执行过的多余的修改

    题目描述

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令:

    1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

    2、 R P Col 把第P支画笔替换为颜色Col。

    为了满足墨墨的要求,你知道你需要干什么了吗?

    输入输出格式

    输入格式:

    第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。

    第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。

    第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

    输出格式:

    对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

    输入输出样例

    输入样例:
    6 5
    1 2 3 4 5 5
    Q 1 4
    Q 2 6
    R 1 2
    Q 1 4
    Q 2 6
    输出样例:
    4
    4
    3
    4

    说明

    对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

     1 #include<cstdio>  
     2 #include<iostream>  
     3 #include<cmath>  
     4 #include<algorithm>  
     5 using namespace std;  
     6   
     7 int CL=1,CR=0,ans=0,tim,n,m,k,cnt=0,sz=0;  
     8 int color[50010],num[1000010];//num存该颜色出现的次数   
     9 int las[50010],answer[200010];  
    10     //las存x个数的前一个颜色,具体操作类似于前向星   
    11 bool vis[50010];//  
    12   
    13 struct XY{ //存sz个询问   
    14     int L,R,id,tm;  
    15 }e[200010];  
    16 struct XX{ //存cnt个修改   
    17     int ps,cl,pre;  
    18 }w[200010];  
    19   
    20   
    21 bool cmp(XY a,XY b){ //莫队的排序(不清楚的可以先做莫队的模板)   
    22     return (a.L/tim)==(b.L/tim)? a.R<b.R : a.L<b.L;  
    23 };  
    24   
    25 void cala(int x){ //相当于莫队的Inc和dec  
    26     if (vis[x]){  
    27         if ((--num[color[x]])==0) --ans;  
    28             //如果此次减掉的是最后一个,则颜色数-1   
    29     }else{  
    30         if ((++num[color[x]])==1) ++ans;  
    31             //如果是新增的数,则颜色数+1   
    32     }  
    33     vis[x]=!vis[x]; //vis可以理解为一个标识符  
    34             //(即是否会影响或在上一次查询中)   
    35             //而更新过答案后应将其重置(取反)  
    36             //设定为取反则在change操作中便于实现   
    37 }    
    38   
    39 void change(int x,int c){ //将第x个改成颜色c   
    40     if (vis[x]){  
    41         cala(x);color[x]=c;cala(x);  
    42             //假如存在x的修改可能影响正确性,则在修改  
    43             //颜色前后都应更新答案,而两个cala则不会改变当前指针   
    44     }else color[x]=c;  
    45 }   
    46   
    47 int main(){  
    48     char cha;int x,y;  
    49     cin >>n>>m;tim=sqrt(n);//tim是莫队的核心了吧   
    50     for (int i=1;i<=n;++i)  
    51         scanf("%d",&color[i]),las[i]=color[i];//初始颜色   
    52     for (int i=1;i<=m;++i){  
    53         cin >>cha;scanf("%d%d",&x,&y);  
    54         if (cha=='R'){  
    55             ++cnt;w[cnt].ps=x;w[cnt].cl=y;w[cnt].pre=las[x];las[x]=y;  
    56                 //前向星式存修改   
    57         }else{  
    58             ++sz;e[sz].L=x;e[sz].R=y;e[sz].id=sz;e[sz].tm=cnt;  
    59                 //存询问时要加上最近一次修改的ID(tm),便于后面操作   
    60         }  
    61     }  
    62       
    63     sort(e+1,e+1+sz,cmp);  
    64       
    65     for (int i=1;i<=sz;++i){  
    66         for (int j=e[i-1].tm+1;j<=e[i].tm;++j)  
    67             change(w[j].ps,w[j].cl); //将所有未修改的点修改   
    68         for (int j=e[i-1].tm;j>=e[i].tm+1;--j)  
    69             change(w[j].ps,w[j].pre);//将所有已修改的点还原  
    70                          //(上次操作多余的修改)  
    71         int l=e[i].L,r=e[i].R;  //下面就是普通莫队了   
    72         while (CL<l) cala(CL++);  
    73         while (CL>l) cala(--CL);  
    74         while (CR<r) cala(++CR);  
    75         while (CR>r) cala(CR--);  
    76         answer[e[i].id]=ans;  
    77     }  
    78     for (int i=1;i<=sz;++i)  
    79         printf("%d
    ",answer[i]);   
    80     return 0;  
    81 }
    View Code
  • 相关阅读:
    数据操作-apply函数族
    11.盛水最多的容器
    canvas绘图
    Nodejs事件监听模块
    http性能测试
    源码解读
    nodejs的一些概念
    http知识补充
    querystring处理参数小利器
    url网址解析的好帮手
  • 原文地址:https://www.cnblogs.com/Dance-Of-Faith/p/7737216.html
Copyright © 2011-2022 走看看