[HEOI2012]採花
阿新 • • 發佈:2018-12-05
第一眼以為是樹套樹qwq
然而n,m<=1e6
記上一個與i顏色相同的位置為nxt[i]
考慮i和nxt[i]會對那些詢問產生貢獻。
發現當右端點R>=i時,
左端點只要滿足nxt[nxt[i]]<l<=nxt[i]就會得到i的貢獻。
由此
把詢問按照R排序
掃描每一個點,對區間 ( nxt[nxt[i]] , nxt[i] ] 加一,查詢時查詢L位置的值即可。
實現可以用樹狀陣列維護差分序列實現。
#include<iostream> #include<cctype> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<cstdlib> #include<algorithm> #define N 4400000 #define eps 1e-7 #define inf 1e9+7 #define ll long long using namespace std; inline int read() { char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*flag; } int n,k,m,l[N],f[N],ans[N]; struct node { int l,r,id; }p[N]; bool cmp(node a,node b) { return a.r<b.r; } int s[N]; void add(int x,int num) { for(;x<=n;x+=((x)&(-x)))s[x]+=num; } int query(int x) { int ans=0; for(;x;x-=((x)&(-x)))ans+=s[x]; return ans; } int main() { int x,i,j; n=read();k=read();m=read(); for(i=1;i<=n;i++) { x=read(); l[i]=f[x];f[x]=i; } for(i=1;i<=m;i++) { p[i].id=i; p[i].l=read(); p[i].r=read(); } sort(p+1,p+m+1,cmp); for(i=1,j=0;i<=m;i++) { while(j<n&&j<p[i].r) { j++; if(!l[j])continue; add(l[l[j]]+1,+1); add(l[j]+1,-1); } ans[p[i].id]=query(p[i].l); } for(i=1;i<=m;i++)printf("%d\n",ans[i]); return 0; }