zoukankan      html  css  js  c++  java
  • 会修修的莫队--BZOJ2120: 数颜色

    $n leq 10000$的数列,$m leq 10000$个操作,一:单点修改;二:查区间不同数字个数。修改数$leq 1000$,数字$leq 1000000$。

    我不会告诉您这是三种写法的双倍经验题!!

    一般可以把查区间不同个数改成:$pre_i$表示$i$之前的一个与她相同的数在哪,然后变成查某个区间$pre_i$在某个范围内的数量。可以主席树,也可分块。修改暴力重构。

    方法三:带修莫队。按L块为第一关键字、R块为第二关键字、时间为第三关键字对询问排序,这样时间指针的移动复杂度是块数量的平方乘修改数。

    理论上块大小取$n^{frac{2}{3}}$是最好的,但是注意一下修改数只有1000。。于是求个导画个图象(用电脑)可得块大小280左右时最优。加了个离散化跑得飞起。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 //#include<queue>
     6 //#include<time.h>
     7 //#include<complex>
     8 #include<algorithm>
     9 #include<stdlib.h>
    10 using namespace std;
    11 
    12 int n,m,lq,lc,tot;
    13 #define maxn 10011
    14 #define maxm 288
    15 int a[maxn],bel[maxn];
    16 struct Ques{int l,r,t,id;}q[maxn];
    17 bool cmp(const Ques a,const Ques b) {return bel[a.l]==bel[b.l]?(bel[a.r]==bel[b.r]?a.t<b.t:a.r<b.r):a.l<b.l;}
    18 struct Modi{int x,a,b;}mo[maxn];
    19 
    20 int lisa[maxn<<1],li;
    21 int ss; int cnt[maxn<<1],ans[maxn];
    22 void modify(int p,int type) {cnt[a[p]]+=type; if (type>0) ss+=cnt[a[p]]==1; else ss-=cnt[a[p]]==0;}
    23 void timemodify(int L,int R,int p,int v) {if (L<=p && p<=R) modify(p,-1); a[p]=v; if (L<=p && p<=R) modify(p,1);}
    24 
    25 int main()
    26 {
    27     scanf("%d%d",&n,&lq); m=280;
    28     for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1; tot=bel[n];
    29     for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisa[++li]=a[i];
    30     char c; lc=0;
    31     for (int i=1,j=0;i<=lq;i++)
    32     {
    33         while ((c=getchar())!='R' && c!='Q');
    34         if (c=='Q')
    35         {
    36             j++; scanf("%d%d",&q[j].l,&q[j].r);
    37             q[j].id=j; q[j].t=lc;
    38         }
    39         else
    40         {
    41             lc++; scanf("%d%d",&mo[lc].x,&mo[lc].b);
    42             mo[lc].a=a[mo[lc].x]; a[mo[lc].x]=mo[lc].b; lisa[++li]=mo[lc].b;
    43         }
    44     }
    45     lq-=lc;
    46     sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1;
    47     for (int i=1;i<=n;i++) a[i]=lower_bound(lisa+1,lisa+1+li,a[i])-lisa;
    48     for (int i=1;i<=lc;i++) mo[i].a=lower_bound(lisa+1,lisa+1+li,mo[i].a)-lisa,
    49     mo[i].b=lower_bound(lisa+1,lisa+1+li,mo[i].b)-lisa;
    50     
    51     sort(q+1,q+1+lq,cmp);
    52     int L=1,R=0,T=lc; ss=0;
    53     for (int i=1;i<=lq;i++)
    54     {
    55         while (T>q[i].t) timemodify(L,R,mo[T].x,mo[T].a),T--;
    56         while (T<q[i].t) T++,timemodify(L,R,mo[T].x,mo[T].b);
    57         while (L<q[i].l) modify(L,-1),L++;
    58         while (L>q[i].l) modify(L-1,1),L--;
    59         while (R<q[i].r) modify(R+1,1),R++;
    60         while (R>q[i].r) modify(R,-1),R--;
    61         ans[q[i].id]=ss;
    62     }
    63     for (int i=1;i<=lq;i++) printf("%d
    ",ans[i]);
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    BZOJ5104 二次剩余板子
    BZOJ5329 [Sdoi2018]战略游戏 圆方树+虚树
    BZOJ1095 动态点分治
    BZOJ3992: [SDOI2015]序列统计
    kd-tree板子
    thusc2018翻车记
    BZOJ5336 DP套DP
    BZOJ4316 仙人掌DP
    问题 F: 最小花费
    问题 C: 热浪
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8571918.html
Copyright © 2011-2022 走看看