P1972 [SDOI2009]HH的项链

Posted benzikun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1972 [SDOI2009]HH的项链相关的知识,希望对你有一定的参考价值。

暑假刚学树状数组时就看了这个题,当时挺无头绪的。之后在昨天写了一道区间查询不同个数的模板题,转头发现这个题也是个模板......

思路:用树状数组维护一个长度为输入总数长度的数组,然后向树状数组输入每一个位置的值,从该位置开始向上更新,每个数组值++,如果这个值在之前最近的位置出现过,所对应的最近位置向上更新,每个数组值--。向下查询的时候返回从下标1位置到当前查询位置所有的不同个数,query(r)-query(l-1)所得到的就是整个区间之内所有不同的数的个数。现在剩下的就是要离线一下,把查询按r的顺序从小到大排一遍,边查询边更新树状数组。

树状数组难的还是想着怎么维护啊。

 

代码写的特别乱,但还是水过了

#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int Maxn=1000010;
int pos[Maxn],tree[Maxn],num[Maxn],n,ans[Maxn];

struct st

    int l,r,flag,ans;
q[Maxn];

bool cmp(st a, st b)

    return a.r<b.r;


void update(int x,int y,int k)

    if(k==1)
    
        for(;x<=n;x+=x & (-x)) tree[x]++;
    
    if(k==2)
    
        for(;x<=n;x+=x & (-x)) tree[x]--;
        for(;y<=n;y+=y & (-y)) tree[y]++;
    


int query(int x)

    int ans=0;
    for(;x>0;x-=x & (-x)) ans+=tree[x];
    return ans;


int main()

    int m; scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&num[i]);
    scanf("%d",&m); int l,r;
    for(int i=1;i<=m;i++) scanf("%d%d",&l,&r); q[i].l=l; q[i].r=r; q[i].flag=i;
    sort(q+1,q+m+1,cmp); int last=1;
    for(int i=1;i<=m;i++)
    
        int j; //cout<<i<<" "<<last<<" "<<q[i].r<<endl;
        for(j=last;j<=q[i].r;j++)
        
            int temp=num[j];
            if(!pos[temp]) update(j,pos[temp],1);
            if(pos[temp]) update(pos[temp],j,2);
            pos[temp]=j;
        
        //for(int i=1;i<=n;i++) cout<<i<<" "<<tree[i]<<endl;
        last=j;
        //cout<<q[i].flag<<endl;
        //cout<<q[i].l<<" "<<q[i].r<<" ";
        if(q[i].r==q[i].l) ans[q[i].flag]=1;
        else ans[q[i].flag]=query(q[i].r)-query(q[i].l-1);
        //if(q[i].r==q[i].l) cout<<1<<endl;
        //else cout<<query(q[i].r)-query(q[i].l-1)<<endl;
    
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;

 

以上是关于P1972 [SDOI2009]HH的项链的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1972 [SDOI2009]HH的项链

luogu P1972 [SDOI2009]HH的项链

题解P1972 [SDOI2009]HH的项链 - 树状数组

P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链