zoukankan      html  css  js  c++  java
  • 洛谷 P1972 HH的项链 题解

    题面

    本题其实主要就这几点:

      1.离线,以右端点排序(从小到大);

      2.建立树状数组c[],c[i]表示从1~i中有多少种不同的数字;

      3.对于每次查询的答案就是sum(r)-sum(l-1);

      4.由于问题是离线排序回答,所以应该注意输出顺序(离散化前的顺序);

    Q:直接统计前缀和,然后对于每次询问O(1)输出不行吗?

    A:当然不行,因为仅仅确保了sum[r]的正确性,无法确保sum[l-1]的正确性;比如说:1 2 3 1 1 1 ,区间[2,5]的个数是3,然而sum[5]=3,sum[1]=1,sum[5]-sum[1]=2;(原因是第一位的1在sum[5]和sum[1]中都算了一遍)

    Q:为什么要离散化?

    A:为了保证我们从左到右扫描扫到i时确保当存在a[i]时1~i中树状数组的答案;这样可以保证不仅仅sum(r)的正确性,也可以保证sum(l-1)的正确性;

    #include <bits/stdc++.h>
    using namespace std;
    int n,m;
    int a[5000010];
    struct haha{
        int pos;
        int l;
        int r;
    }lala[5000010];
    bool cmp(haha x,haha y)
    {
        return x.r<y.r;
    }
    int c[5000010];
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int x,int value)
    {
        while(x<=n){
            c[x]+=value;
            x+=lowbit(x);
        }
        return;
    }
    int sum(int x)
    {
        int res=0;
        while(x>0){
            res+=c[x];
            x-=lowbit(x);
        }
        return res;
    }
    int nxt[1000010];
    int ans[1000010];
    int main ()
    {
         cin>>n;
         for(register int i=1;i<=n;i++){
             scanf("%d",&a[i]);
         }
         cin>>m;
         for(register int i=1;i<=m;i++){
             int l,r;
             scanf("%d%d",&l,&r);
             lala[i].pos=i;
             lala[i].l=l;
             lala[i].r=r;
         }
         sort(lala+1,lala+1+m,cmp);
         int st=1;
         for(register int i=1;i<=m;i++){
             for(register int j=st;j<=lala[i].r;j++){
                 if(nxt[a[j]]){
                     add(nxt[a[j]],-1);            
                 }
                 add(j,1);
                 nxt[a[j]]=j;            
             }
             st=lala[i].r+1;
             ans[lala[i].pos]=sum(lala[i].r)-sum(lala[i].l-1);
         }
         for(int i=1;i<=m;i++){
             cout<<ans[i]<<endl;
         }
    }
  • 相关阅读:
    <11>改变图像的尺寸,方便上传服务器
    <10>获取当前时间
    <09>获得字符串的size
    <08>时间戳的转换
    <07>手机号码验证
    <06>邮箱的验证
    <05>判断字符串是否为空
    WKWebView的一些知识
    objc_setAssociatedObject 使用
    linker command failed with exit code 1 (use -v to see invocation) 编译报错原因
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11320296.html
Copyright © 2011-2022 走看看