P1972 [SDOI2009]HH的項鍊
阿新 • • 發佈:2020-10-26
P1972 [SDOI2009]HH的項鍊
這題看起來可以用莫隊做,本來想水一下的,然而我逛了一圈題解發現資料被加強了。
我稍微想了一下主席樹,感覺好像維護起來沒什麼用,可能是我太菜了。
Std:
個人的理解
其實這種想法就是在進行一種去重(消去重複的影響),讓統計變成最簡單的區間求和
既然我們區間顏色重疊會影響統計,那麼我們只要記錄當前最有效的顏色即可,區間右端點的排序保證了這種有效性。
Code:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f #define maxn 1000305 #define minn -105 #define ll long long int #define ull unsigned long long int #define uint unsigned int inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'|ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } struct Query { int l,r,id; bool operator<(const Query& sec)const { return r<sec.r; } }q[maxn]; int tree[maxn]; int a[maxn],ans[maxn],pos[maxn]; int n,m; void renew(int x,int k) { for(;x<=n;x+=(x&-x))tree[x]+=k; } int cal(int x) { int t=0; for(;x;x-=(x&-x))t+=tree[x]; return t; } int main() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); } m=read(); for(int i=0;i<m;i++) { q[i].l=read(),q[i].r=read();q[i].id=i; } sort(q,q+m); int cur=0; for(int i=0;i<m;i++) { while(cur<q[i].r) { cur++; if(pos[a[cur]]!=0)renew(pos[a[cur]],-1); renew(cur,1); pos[a[cur]]=cur; } ans[q[i].id]=cal(q[i].r)-cal(q[i].l-1); } for(int i=0;i<m;i++) { cout<<ans[i]<<"\n"; } return 0; }