• 1878. [SDOI2009]HH的项链【线段树 或 莫队】


    Description

    HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一
    段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一
    个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只
    好求助睿智的你,来解决这个问题。

    Input

    第一行:一个整数N,表示项链的长度。 
    第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 
    第三行:一个整数M,表示HH询问的个数。 
    接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
    N ≤ 50000,M ≤ 200000。

    Output

    M行,每行一个整数,依次表示询问对应的答案。

    Sample Input

    6
    1 2 3 4 3 5
    3
    1 2
    3 5
    2 6

    Sample Output

    2
    2
    4

    第一个线段树第二个莫队

    线段树:
    啊这个题的IDEA炒鸡妙啊……让我情不自禁想写一发题解
    (其实是我怕这次抄题解会了后下次就不会了……)
    我们先将询问按照结束点升序排序
    用now保存当前询问的是第几个
    线段树保存的是当前下标是否有珠子(0/1表示)
    然后从1~n依次访问项链。
    当前访问中,我们要做的有两件事:
    第一件:将当前点的珠子修改成1
    第二件:将上一个和当前珠子编号相同的珠子设为0
              (因为我们要保证当前序列里不能有重复编号的珠子
                而当前珠子以后的访问都不需要上一个重复编号的珠子了
                因为我们完全可以用当前珠子来统计区间[L,R]之间的个数
                如何统计呢?求个和就好了啊……)
    将当前珠子的修改做好后,就要查询了。如果当前询问(now)的右端点和当前珠子是一样的
    就查询[L,R]的和就好了,这个和就代表着区间内不同种的数量
    毕竟我们已经把重复的珠子都去重了……

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 struct node
     7 {
     8     int x,y,num,ans;
     9 }ask[200001];
    10 struct node1
    11 {
    12     int val;
    13 }Segt[200001];
    14 bool cmp(node a,node b)
    15 {
    16     return a.y<b.y;
    17 }
    18 bool cmp1(node a,node b)
    19 {
    20     return a.num<b.num;
    21 }
    22 
    23 int last[1000001],a[50001];
    24 int Query(int node,int l,int r,int l1,int r1)
    25 {
    26     if (l>r1 || r<l1)
    27         return 0;
    28     if (l1<=l && r<=r1)
    29         return Segt[node].val;
    30     int mid=(l+r)/2;
    31     return Query(node*2,l,mid,l1,r1)+
    32            Query(node*2+1,mid+1,r,l1,r1);
    33 }
    34 
    35 void Update(int node,int l,int r,int x,int k)
    36 {
    37     if (l==r)
    38         Segt[node].val=k;
    39     else
    40     {
    41         int mid=(l+r)/2;
    42         if (x<=mid)    Update(node*2,l,mid,x,k);
    43         else Update(node*2+1,mid+1,r,x,k);
    44         Segt[node].val=Segt[node*2].val+Segt[node*2+1].val;
    45     }
    46 }
    47 
    48 int main()
    49 {
    50     int n,m;
    51     scanf("%d",&n);
    52     for (int i=1;i<=n;++i)
    53         scanf("%d",&a[i]);
    54     scanf("%d",&m);
    55     for (int i=1;i<=m;++i)
    56     {
    57         scanf("%d%d",&ask[i].x,&ask[i].y);
    58         ask[i].num=i;
    59     }
    60     sort(ask+1,ask+m+1,cmp);
    61     int now=1;
    62     for (int i=1;i<=n;++i)
    63     {
    64         Update(1,1,n,i,1);
    65         if (last[a[i]]!=0)
    66             Update(1,1,n,last[a[i]],0);
    67         last[a[i]]=i;
    68         while (ask[now].y==i)
    69         {
    70             ask[now].ans=Query(1,1,n,ask[now].x,ask[now].y);
    71             ++now;
    72         }
    73     }
    74     sort(ask+1,ask+m+1,cmp1);
    75     for (int i=1;i<=m-1;++i)
    76         printf("%d
    ",ask[i].ans);
    77     printf("%d",ask[m].ans);
    78 }

    莫队:

    入门题

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define MAXN (1000000+10)
     7 using namespace std;
     8 struct node
     9 {
    10     int l,r,ord,id,ans;
    11 }Ask[MAXN];
    12 int l=1,r=0,now,n,m;
    13 int cnt[MAXN],a[MAXN]; 
    14 bool cmp1(node a,node b){return a.id==b.id?a.r<b.r:a.id<b.id;}
    15 bool cmp2(node a,node b){return a.ord<b.ord;}
    16 
    17 void Del(int x)
    18 {
    19     cnt[a[x]]--;
    20     if (!cnt[a[x]]) now--;
    21 }
    22 void Ins(int x)
    23 {
    24     if (!cnt[a[x]]) now++;
    25     cnt[a[x]]++;
    26 }
    27 void MO(int x)
    28 {
    29     int L=Ask[x].l,R=Ask[x].r;
    30     while (l>L) Ins(--l);
    31     while (l<L) Del(l++);
    32     while (r>R) Del(r--);
    33     while (r<R) Ins(++r);
    34     Ask[x].ans=now;
    35 }
    36 
    37 int main()
    38 {
    39     scanf("%d",&n);
    40     int len=sqrt(n);
    41     for (int i=1;i<=n;++i)
    42         scanf("%d",&a[i]);
    43     scanf("%d",&m);
    44     for (int i=1;i<=m;++i)
    45     {
    46         scanf("%d%d",&Ask[i].l,&Ask[i].r);
    47         Ask[i].id=Ask[i].l/len;
    48         Ask[i].ord=i;
    49     }
    50     sort(Ask+1,Ask+m+1,cmp1);
    51     for (int i=1;i<=m;++i)
    52         MO(i);
    53     sort(Ask+1,Ask+m+1,cmp2);
    54     for (int i=1;i<=m;++i)
    55         printf("%d
    ",Ask[i].ans);
    56 }
  • 相关阅读:
    20162302预备作业02
    20162302预备作业01
    设计模式第二次作业
    设计模式第一次作业
    项目选题报告(团队)
    高级软件工程结对第二次作业
    高级软件工程团队第一次作业
    高级软件工程结对第一次作业
    高级软件工程第二次作业
    高级软件工程第一次作业--准备
  • 原文地址:https://www.cnblogs.com/refun/p/8682228.html
Copyright © 2020-2023  润新知