码迷,mamicode.com
首页 > 其他好文 > 详细

P1972 [SDOI2009]HH的项链

时间:2019-10-07 09:49:23      阅读:62      评论:0      收藏:0      [点我收藏+]

标签:fine   update   last   name   iostream   ret   end   思路   lag   

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

思路:用树状数组维护一个长度为输入总数长度的数组,然后向树状数组输入每一个位置的值,从该位置开始向上更新,每个数组值++,如果这个值在之前最近的位置出现过,所对应的最近位置向上更新,每个数组值--。向下查询的时候返回从下标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的项链

标签:fine   update   last   name   iostream   ret   end   思路   lag   

原文地址:https://www.cnblogs.com/benzikun/p/11629164.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!