BZOJ2743:[HEOI2012]采花——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=2743
萧薰儿是古国的公主,平时的一大爱好是采花。
今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。
花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴!同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。
由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了m个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案!),最后会选择令公主最高兴的行程(为了拿到更多奖金!)。
听说又是一道套路题……?还是HH的项链变形版?emm那不是个分块/莫队吗,这题数据范围这么大怎么做a……
以及这题被某大佬标为0分sb题emmm……感觉到了深深的差距。
参考:http://www.cnblogs.com/GXZlegend/p/6633834.html
如果我们知道HH的项链如何用树状数组来做的话这题就异常简单了。
我们将询问离线,然后从左往右扫,保证每种颜色出现第二次的位置标上1,这样我们询问$[l,r]$就相当于直接树状数组区间查询$[1,r]$的1的个数就行了。
#include<map> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=2e6+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct data{ int l,r,id; }d[N]; int n,m,c,b[N],tr[N],ans[N],lst[N],nxt[N]; bool vis[N]; inline bool cmp(data a,data b){ return a.l<b.l; } inline int lowbit(int t){return t&-t;} inline void add(int x,int y){ if(!x)return; for(int i=x;i<=n;i+=lowbit(i))tr[i]+=y; } inline int qry(int x){ int res=0; for(int i=x;i;i-=lowbit(i))res+=tr[i]; return res; } int main(){ n=read(),c=read(),m=read(); for(int i=1;i<=n;i++){ b[i]=read();nxt[lst[b[i]]]=i; if(lst[b[i]]&&!vis[b[i]])vis[b[i]]=1,add(i,1); lst[b[i]]=i; } nxt[0]=0; for(int i=1;i<=m;i++){ d[i].l=read(),d[i].r=read(); d[i].id=i; } sort(d+1,d+m+1,cmp); for(int i=1,j=1;i<=n;i++){ add(nxt[i-1],-1);add(nxt[nxt[i-1]],1); while(d[j].l==i){ ans[d[j].id]=qry(d[j].r); j++; } } for(int i=1;i<=m;i++)printf("%d\n",ans[i]); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++