zoukankan      html  css  js  c++  java
  • P1972 HHのnecklace 离线+树状数组

    此题莫队可过

    然而太难了......

    我在胡雨菲那看的解法,然后自己打了一波,调了一个错,上交,自信AC。

    做法:离线,对于L排序。

    每种颜色可能出现很多次,那么我们如何不算重复呢?

    只需把[L,n]区间内第一个出现的该颜色标为1即可。

    所以我们记录下每个下标i所对应的颜色下一次出现的位置next[i]即可。

    每次L挪动时,挪动的每个位置都-1(一定是1不是0),然后把next[i]+1即可。

    所求即为∑[1,R]。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #define lowbit(a) (a&(-a))
     4 #define say(a) printf(#a);
     5 #define ln printf("
    ");
     6 using namespace std;
     7 const int N = 500010;
     8 
     9 struct Question
    10 {
    11     int L,R,ans,num;
    12 }quest[200010];
    13 int next[N],lastfind[N],x[N],tree[N],a[N];
    14 int n;
    15 bool cmp1(Question x,Question y) {return x.L<y.L;}
    16 bool cmp2(Question x,Question y) {return x.num<y.num;}
    17 void add(int x,int v)
    18 {
    19     if(x==0) return;
    20     for(int i=x;i<=n;i+=lowbit(i)) tree[i]+=v;
    21     return;
    22 }
    23 int getsum(int x)
    24 {
    25     if(x==0) return 0;
    26     int ans=0;
    27     for(int i=x;i>0;i-=lowbit(i)) ans+=tree[i];
    28     return ans;
    29 }
    30 int main()
    31 {
    32     scanf("%d",&n);
    33     for(int i=1;i<=n;i++) scanf("%d",&a[i]),x[i]=a[i];
    34     int m;
    35     scanf("%d",&m);
    36     for(int i=1;i<=m;i++) scanf("%d%d",&quest[i].L,&quest[i].R),quest[i].num=i;
    37     sort(x+1,x+n+1);
    38     int k=0;
    39     for(int i=1;i<=n;i++) if(x[i]!=x[i-1]) x[++k]=x[i]; /// 离散化
    40     for(int i=1;i<=n;i++)
    41     {
    42         int p=lower_bound(x+1,x+k+1,a[i])-x;///预处理出next[i]
    43         if(lastfind[p]) next[lastfind[p]]=i;
    44         else add(i,1);///p -> i 这里调一个错,之前写的p
    45         lastfind[p]=i;
    46     }
    47     int j=1,ans=0;
    48     //for(int i=1;i<=6;i++) printf("%d ",getsum(i)-getsum(i-1));ln;
    49     sort(quest+1,quest+m+1,cmp1);
    50     for(int i=1;i<=m;i++)
    51     {
    52         while(j<quest[i].L)
    53         {
    54 
    55             add(j,-1);
    56             add(next[j],1);
    57             j++;
    58         }
    59         //for(int i=1;i<=6;i++) printf("%d ",getsum(i)-getsum(i-1));ln
    60         quest[i].ans=getsum(quest[i].R);
    61     }
    62     sort(quest+1,quest+m+1,cmp2);
    63     for(int i=1;i<=m;i++) printf("%d
    ",quest[i].ans);
    64     return 0;
    65 }
    AC代码如下:

    用了一些特殊的调试手法。。。

  • 相关阅读:
    luogu2568GCD题解--欧拉函数
    POJ1845Sumdiv题解--约数之和
    luogu1731生日蛋糕题解--恶心剪枝
    luogu1156垃圾陷阱题解--背包DP
    CF336C-Vasily the Bear and Sequence题解--贪心
    luogu2261余数求和题解--整除分块
    UVA10140PrimeDistance题解--质数/技巧
    CSP2019 游记
    CSP-SJX2019 和积和
    NOIP2018 游记
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/8696078.html
Copyright © 2011-2022 走看看