1. 程式人生 > >【BZOJ 1878】 HH的項鏈

【BZOJ 1878】 HH的項鏈

lock amp urn blank return cstring using code !=

【題目鏈接】

https://www.lydsy.com/JudgeOnline/problem.php?id=1878

【算法】

顯然,在線算法是不可做的,考慮離線算法

筆者的做法是莫隊算法,時間復雜度 : O(nsqrt(n))(sqrt表示開方)

但是,樹狀數組的效率更高,下面講一講這種高效的做法 :

不妨將所有詢問按右端點排序

對於每次詢問,我們只考慮每種顏色最後出現的一次,用樹狀數組維護每一個位置是否對答案產生“貢獻“

具體來說,我們用一個Next數組記錄這種顏色上次出現的位置,然後,對於每個位置i,如果存在Next[i],將樹狀數組中的Next[i]減1,將這個位置加1即可

時間復雜度 :O(nlog(n))

【代碼】

我的代碼(莫隊) :

#include<bits/stdc++.h>
using namespace std;
#define MAXN 50010
#define MAXS 1000010
#define MAXM 200010

struct Query
{
    int l,r;
    int id;
} q[MAXM],b[MAXM];

int i,j,k,n,m,block,len,t,sum,l,r;
int a[MAXN],s[MAXS],ans[MAXM];

inline 
bool cmp1(Query a,Query b) { return a.l < b.l; } inline bool cmp2(Query a,Query b) { return a.r < b.r; } inline void add(int l,int r,int val) { int i; for (i = l; i <= r; i++) { if (s[a[i]] == 1 && val == -1) sum--; if (s[a[i]] == 0 && val == 1
) sum++; s[a[i]] += val; } } int main() { scanf("%d",&n); for (i = 1; i <= n; i++) scanf("%d",&a[i]); scanf("%d",&m); for (i = 1; i <= m; i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id = i; } sort(q+1,q+m+1,cmp1); len = (int)sqrt(n); block = n / len + (n % len != 0); j = 1; for (i = 1; i <= block; i++) { t = 0; sum = 0; while (j <= m && q[j].l > (i - 1) * len && q[j].l <= i * len) { b[++t] = q[j]; j++; } sort(b+1,b+t+1,cmp2); l = b[1].l; r = b[1].l - 1; for (k = 1; k <= t; k++) { if (l < b[k].l) add(l,b[k].l-1,-1); else if (l > b[k].l) add(b[k].l,l-1,1); add(r+1,b[k].r,1); ans[b[k].id] = sum; l = b[k].l; r = b[k].r; } add(l,r,-1); } for (i = 1; i <= m; i++) printf("%d\n",ans[i]); return 0; }

黃學長的代碼(樹狀數組)

(http://hzwer.com/3007.html)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
    int x=0;char ch=getchar();
    while(ch<0||ch>9){ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x;
}
int n,m,mx;
int a[50005],next[50005],t[50005];
int p[1000005];
struct data{int l,r,id,ans;}q[200005];
bool cmp1(data a,data b)
{return a.l==b.l?a.r<b.r:a.l<b.l;}
bool cmp2(data a,data b)
{return a.id<b.id;}
int lowbit(int x){return x&(-x);}
void update(int x,int v)
{
    for(int i=x;i<=n;i+=lowbit(i))
        t[i]+=v;
}
int ask(int x)
{
    int tmp=0;
    for(int i=x;i>0;i-=lowbit(i))
        tmp+=t[i];
    return tmp;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),mx=max(mx,a[i]);
    for(int i=n;i>0;i--)
        next[i]=p[a[i]],p[a[i]]=i;
    for(int i=1;i<=mx;i++)
        if(p[i])update(p[i],1);
    m=read();
    for(int i=1;i<=m;i++)
        q[i].l=read(),q[i].r=read(),q[i].id=i;
    sort(q+1,q+m+1,cmp1);
    int l=1;
    for(int i=1;i<=m;i++)
    {
        while(l<q[i].l)
        {
            if(next[l])update(next[l],1);
            l++;
        }
        q[i].ans=ask(q[i].r)-ask(q[i].l-1);
    }
    sort(q+1,q+m+1,cmp2);
    for(int i=1;i<=m;i++)
        printf("%d\n",q[i].ans);
    return 0;
}

【BZOJ 1878】 HH的項鏈