[bzoj2743][HEOI2012]采花
来自FallDream的博客,未经允许,请勿转载,谢谢。
萧芸斓是Z国的公主,平时的一大爱好是采花。
今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴!同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了m个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案!),最后会选择令公主最高兴的行程(为了拿到更多奖金!)。
n,m<=10^6
也就是求区间数量大于1的颜色的个数。
考虑从左到右,维护每个左端点对应的答案。每次加入一个颜色c,last[last[c]]+1到last[c]的答案会+1,线段树维护即可。
#include<iostream> #include<cstdio> #include<vector> #define pa pair<int,int> #define mp(x,y) make_pair(x,y) #define MN 1000000 #define N 1048576 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int n,c,m,Ans[MN+5],a[MN+5],last[MN+5],Last[MN+5],T[N*2+5]; vector<pa> v[MN+5]; inline int Query(int l,int r) { int sum=0; for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1) { if(~l&1) sum+=T[l+1]; if( r&1) sum+=T[r-1]; } return sum; } inline void Renew(int x,int ad) { for(T[x+=N]+=ad,x>>=1;x;x>>=1) T[x]=T[x<<1]+T[x<<1|1]; } int main() { n=read();c=read();m=read(); for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<=m;++i) { int l=read(),r=read(); v[r].push_back(mp(l,i)); } for(int i=1;i<=n;++i) { if(last[a[i]]) Renew(Last[a[i]]+1,1),Renew(last[a[i]]+1,-1); Last[a[i]]=last[a[i]];last[a[i]]=i; for(int j=0;j<v[i].size();++j) Ans[v[i][j].second]=Query(1,v[i][j].first); } for(int i=1;i<=m;++i) printf("%d\n",Ans[i]); return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream