• 题解:[SDOI2009]HH的项链


    刚开始暴力开数组打标记的方法水过四十分,代码是这样的

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 int a[500005], num[1000005];
     6 int m, n, l, r, ans;
     7 int read(){ 
     8     int x=0,f=1; 
     9     char c=getchar(); 
    10     while(c>'9'||c<'0') { 
    11         if(c=='-')f=-1; 
    12         c=getchar(); 
    13         } 
    14     while(c>='0'&&c<='9')
    15         x=x*10+c-'0',c=getchar(); 
    16     return x*f; 
    17 } 
    18 int main(){
    19     n=read();
    20     for(int i=1; i<=n; i++){
    21         a[i]=read();
    22     }
    23     m=read();
    24     while(m--){
    25         ans=0;
    26         memset(num, 0, sizeof(num));
    27         l=read();
    28         r=read();
    29         for(int i=l; i<=r; i++){
    30             if(!num[a[i]]){
    31                 ans++;
    32                 num[a[i]]=1;
    33             }
    34         }
    35         printf("%d
    ",ans); 
    36     }
    37     return 0;
    38 }

    其实这题有好多做法,线段树,树状数组,莫队啊qwq

    暴力的话可以使用莫队来做

    离线的话可以使用排序加树状数组或者线段树来做

    强制在线可以使用主席树来做

    这是八十分的莫队(据书名号大爷说努力努力改改快读改改块的大小就卡过了qwq,然而我懒不想改……)

    可能洛谷强化数据后卡了莫队两个点qwq

    算是莫队入门题

    先按照区间左右端点排序然后依次处理,挺好理解的

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 using namespace std;
     7 int sum, tot[1000010], ans[2000010], color[500010], pos[500010];
     8 struct node{
     9     int l, r, id;
    10 }ask[2000010];
    11 int n, m, qwq, L, R;
    12 int read(){
    13     int s=0,fh=1;char ch=getchar();
    14     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
    15     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
    16     return s*fh;
    17 }
    18 bool cmp(node a,node b){
    19     if(pos[a.l]==pos[b.l]) return a.r<b.r;
    20     return a.l<b.l;
    21 }
    22 void del(int C){ tot[C]--; if(tot[C]==0) sum--;}
    23 void add(int C){ tot[C]++; if(tot[C]==1) sum++;}
    24 int main(){
    25     n=read();
    26     for(int i=1; i<=n; i++)    color[i]=read();
    27     qwq=(int)sqrt(n);
    28     m=read();
    29     for(int i=1; i<=m; i++){
    30         ask[i].l=read();
    31         ask[i].r=read();
    32         ask[i].id=i;
    33     }
    34     for(int i=1; i<=n; i++) pos[i]=(int)(i-1)/qwq+1;
    35     sort(ask+1, ask+m+1, cmp);
    36     L=1;
    37     R=0;
    38     memset(tot, 0, sizeof(tot));
    39     for(int i=1; i<=m; i++){
    40         while(L<ask[i].l){
    41             del(color[L]);
    42             L++;
    43         }
    44         while(L>ask[i].l){
    45             L--;
    46             add(color[L]);
    47         }
    48         while(R<ask[i].r){
    49             R++;
    50             add(color[R]);
    51         }
    52         while(R>ask[i].r){
    53             del(color[R]);
    54             R--;
    55         }
    56         ans[ask[i].id]=sum;
    57     }
    58     for(int i=1; i<=m; i++)    printf("%d
    ",ans[i]);
    59     return 0;
    60 }

    接下来是能A过这道题的线段树orzzz

    求和函数一个大于小于号卡了我一个小时qwq真是绝望

    最近总是在疯狂RE和MLE中徘徊

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=500005;
     6 int sum[maxn*4], n, m, color[maxn], cnt, ans[maxn], last[maxn*2];
     7 struct node{
     8     int l, r, id;
     9 }ask[maxn];
    10 bool cmp(node a,node b){
    11     if(a.r==b.r) return a.l<b.l;
    12     return a.r<b.r;
    13 }
    14 void pushup(int rt){
    15     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    16 }
    17 void update(int x, int c, int l, int r, int rt){
    18     if(l==r && x==l){
    19         sum[rt]=c;
    20         return;
    21     }
    22     int mid=(l+r)>>1;
    23     if(x<=mid) update(x, c, l, mid, rt<<1);
    24     else   update(x, c, mid+1, r, rt<<1|1);
    25     pushup(rt);
    26 }
    27 int query(int L, int R, int l, int r, int rt){
    28     if(L<=l && r<=R) return sum[rt];
    29     int mid=(l+r)>>1;
    30     int ans=0;
    31     if(L<=mid) ans+=query(L, R, l, mid, rt<<1);
    32     if (R>mid) ans+=query(L, R, mid+1, r, rt<<1|1);
    33     return ans;
    34 }
    35 int main(){
    36     scanf("%d",&n);
    37     for(int i=1; i<=n; i++)    scanf("%d",&color[i]);
    38     scanf("%d",&m);
    39     for(int i=1; i<=m; i++){
    40         scanf("%d%d",&ask[i].l,&ask[i].r);
    41         ask[i].id=i;
    42     }
    43     sort(ask+1, ask+m+1, cmp);
    44     cnt=1;
    45     for(int i=1; i<=n; i++){
    46         update(i, 1, 1, n, 1);
    47         if(last[color[i]]) update(last[color[i]], 0, 1, n, 1);
    48         last[color[i]]=i;
    49         while(ask[cnt].r==i){
    50             ans[ask[cnt].id]=query(ask[cnt].l, ask[cnt].r, 1, n, 1);
    51             cnt++;
    52         }
    53     }
    54     for(int i=1; i<=m; i++)    printf("%d
    ",ans[i]);
    55     return 0;
    56 }

     然后是主席树做法,先去吃饭qwq,等会儿回来更

  • 相关阅读:
    Centos 环境变量
    Centos 多线程下载工具-axel
    【Sprint3冲刺之前】项目可行性研究报告
    【Sprint3冲刺之前】TDzhushou软件项目测试计划书
    【Sprint3冲刺之前】日历表的事件处理和管理(刘铸辉)
    【Sprint3冲刺之前】项目完成时间表
    【Sprint3冲刺之前】敏捷团队绩效考核(刘铸辉)
    【每日Scrum】第八天(4.29) TD学生助手Sprint2
    【每日Scrum】第七天(4.28)Sprint2总结性会议
    需求分析
  • 原文地址:https://www.cnblogs.com/Aze-qwq/p/9857158.html
Copyright © 2020-2023  润新知