• 算法复习——带修改莫队(bzoj2453)


    题目:

    Description

    你小时候玩过弹珠吗?
    小朋友A有一些弹珠,A喜欢把它们排成队列,从左到右编号为1到N。为了整个队列鲜艳美观,小朋友想知道某一段连续弹珠中,不同颜色的弹珠有多少。当然,A有时候会依据个人喜好,替换队列中某个弹珠的颜色。但是A还没有学过编程,且觉得头脑风暴太浪费脑力了,所以向你来寻求帮助。

    Input

    输入文件第一行包含两个整数N和M。
    第二行N个整数,表示初始队列中弹珠的颜色。
    接下来M行,每行的形式为“Q L R”或“R x c”,“Q L R”表示A想知道从队列第L个弹珠到第R个弹珠中,一共有多少不同颜色的弹珠,“R x c”表示A把x位置上的弹珠换成了c颜色。

    Output

    对于每个Q操作,输出一行表示询问结果。

    Sample Input


    2 3
    1 2
    Q 1 2
    R 1 2
    Q 1 2

    Sample Output

    2
    1

    HINT

    对于100%的数据,有1 ≤ N ≤ 10000, 1 ≤ M ≤ 10000,小朋友A不会修改超过1000次,所有颜色均用1到10^6的整数表示。

    Source

    题解:

      带修改莫队就是莫队原有排序基础上加个第三关键字:时间,注意排序的顺序都是以所在块为顺序另外利用判断是否在指针内的数组visit[i]结合一个巧妙的change和update操作,另外注意分块的大小为n的2/3次方.

    具体见http://blog.csdn.net/doyouseeman/article/details/51869932

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=1e4+5;
    const int M=1e6+5;
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    struct node
    {
      int l,r,x,id;
    }ask[N];
    struct node2
    {
      int po,va,pre;
    }modi[N];
    int s,n,m,cnt[M],last[N],tots,tota,totm,num[N],id[N],head,tail,now,ans,anss[N];
    bool visit[N];
    inline bool cmp(node a,node b)
    {
      return (id[a.l]<id[b.l])||(id[a.l]==id[b.l]&&id[a.r]<id[b.r])||(id[a.l]==id[b.l]&&id[a.r]==id[b.r]&&a.x<b.x);
    }
    inline void update(int pos)
    {
      if(visit[pos])
      {
        cnt[num[pos]]--;
        if(!cnt[num[pos]])  ans--;
      }
      else
      {
        cnt[num[pos]]++;
        if(cnt[num[pos]]==1)  ans++;
      }
      visit[pos]^=1;
    }
    inline void change(int pos,int val)
    {
      if(visit[pos])
      {
        update(pos);
        num[pos]=val;
        update(pos);
      }
      else
        num[pos]=val;
    }
    int main()
    {
      n=R(),m=R();s=pow(n,2.0/3.0);
      for(int i=1;i<=n;i++)
        num[i]=R(),last[i]=num[i];
      for(int i=1;i<=n;i++)
        id[i]=i/s+1;int a,b;char t[5];
      for(int i=1;i<=m;i++)
      {
        scanf("%s",t);
        if(t[0]=='Q')
          ask[++tota].l=R(),ask[tota].r=R(),ask[tota].x=totm,ask[tota].id=tota;
        else
          modi[++totm].po=R(),modi[totm].va=R(),modi[totm].pre=last[modi[totm].po],last[modi[totm].po]=modi[totm].va;
      } 
      sort(ask+1,ask+tota+1,cmp);head=1;
      for(int i=1;i<=tota;i++)
      {
        if(ask[i].x>now)  for(int j=now+1;j<=ask[i].x;j++)  change(modi[j].po,modi[j].va);
        else for(int j=now;j>=ask[i].x+1;j--)  change(modi[j].po,modi[j].pre);
        if(head<ask[i].l)  for(int j=head;j<=ask[i].l-1;j++)  update(j);
        else for(int j=ask[i].l;j<=head-1;j++)  update(j);
        if(tail>ask[i].r)  for(int j=ask[i].r+1;j<=tail;j++)  update(j);
        else for(int j=tail+1;j<=ask[i].r;j++)  update(j);
        head=ask[i].l,tail=ask[i].r,now=ask[i].x,anss[ask[i].id]=ans;
      }
      for(int i=1;i<=tota;i++)
        printf("%d
    ",anss[i]);
      return 0;
    }
     
     
  • 相关阅读:
    Python--文件操作
    Python--数据类型整理
    u-boot之NAND启动与NOR启动的区别
    u-boot之make all执行过程分析
    编译过程和符号表重定位问题、静态和动态链接
    u-boot之make <board_name>_config执行过程分析
    u-boot之ARM920T的start.S分析
    在使用Myeclipse时,用Tomcat添加部署项目的时候报错,或启动tomcat报错
    关于JDK,tomcat,eclipse的配置
    我的博客
  • 原文地址:https://www.cnblogs.com/AseanA/p/7512138.html
Copyright © 2020-2023  润新知