zoukankan      html  css  js  c++  java
  • bzoj1878[SDOI2009]HH的项链

    bzoj1878[SDOI2009]HH的项链

    题意:

    N个数,M个询问求区间[L,R]中包含了多少种不同的数。

    题解:

    莫队好像可以做~但正解是树状数组。先将询问按左端点排序,并求出每个数的下一个与它相等的数的位置,同时将每个数第一次出现的位置在树状数组中置为1,此时query(x)求出来的就是1到x里有多少个不同的数。枚举排序后的询问,将当前左端点向右移动,每右移一位就将原位置的数的下一个与它相同的数的位置在树状数组中置为1,保证如果这个数在[l,r]中出现不会漏算。当左端点移动到询问的左端点位置时,就输出query(r)-query(l-1),表示l到r里有多少个不同的数。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 50100
     6 #define lb(x) x&-x;
     7 using namespace std;
     8 
     9 int a[maxn],last[maxn*20],next[maxn],sm[maxn],n,m;
    10 struct ask{int l,r,ans,id;}; ask asks[maxn*6];
    11 bool cmp1(ask a,ask b){return a.l<b.l;}
    12 bool cmp2(ask a,ask b){return a.id<b.id;}
    13 inline void update(int x,int v){while(x<=n){sm[x]+=v,x+=lb(x);}}
    14 inline int query(int x){int q=0; while(x>0){q+=sm[x],x-=lb(x);} return q;}
    15 int main(){
    16     scanf("%d",&n); inc(i,1,n)scanf("%d",&a[i]);
    17     scanf("%d",&m); inc(i,1,m)scanf("%d%d",&asks[i].l,&asks[i].r),asks[i].id=i;
    18     memset(last,0,sizeof(last)); inc(i,1,n){if(last[a[i]])next[last[a[i]]]=i;else update(i,1); last[a[i]]=i;}
    19     sort(asks+1,asks+1+m,cmp1); int l=1;
    20     inc(i,1,m){
    21         while(l<asks[i].l){if(next[l])update(next[l],1); l++;}
    22         asks[i].ans=query(asks[i].r)-query(asks[i].l-1);
    23     }
    24     sort(asks+1,asks+1+m,cmp2); inc(i,1,m)printf("%d
    ",asks[i].ans);
    25     return 0;
    26 }

    20160525

  • 相关阅读:
    获取office版本
    SQL中判断字符串中包含字符的方法
    wpf 多表头
    webservice MaxReceivedMessageSize :已超过传入消息(65536)的最大消息大小配额
    QQ检测登陆及QQ协议
    ssl-openssl简介
    抓包及分析(wireshark&tcpdump)
    Git的一些东西(后续补充)
    SSH实现隧道功能穿墙
    Nmap参考指南(Man Page)
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5698469.html
Copyright © 2011-2022 走看看