把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P4113 [HEOI2012]采花

题面传送门
和HH的项链那道题有点像。
将所有询问离线,按右端点排序。
维护每种颜色最近出现的和第二近出现的。当加入一种颜色时,将其第二近出现的删掉,使原来第一出现的变为第二出现的。
然后来了一个询问,查询比他大的数的个数就是答案,树状数组或线段树或平衡树随便维护一下就好了。
代码实现:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,k,x,y,f[2000039],tot,pus,a[2000039],head=1,g1[2000039],g2[2000039],ans[2000039];
struct yyy{
	int x,y,num;
}s[2000039];
inline bool cmp(yyy x,yyy y){return x.y<y.y;}
inline void read(int &x){
	char s=getchar();x=0;
	while(s<'0'||s>'9') s=getchar();
	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
inline void print(int x){
	if(x>9) print(x/10);
	putchar(x%10+48);
}
inline void get(int x,int y){while(x<=n) f[x]+=y,x+=x&-x;}
inline int find(int x){int ans=0;while(x) ans+=f[x],x-=x&-x;return ans;}
int main(){
	register int i;
	read(n);read(k);read(m);
	for(i=1;i<=n;i++) read(a[i]);
	for(i=1;i<=m;i++) read(s[i].x),read(s[i].y),s[i].num=i;
	sort(s+1,s+m+1,cmp);
	for(i=1;i<=n;i++){
	    if(g1[a[i]]){
			if(g2[a[i]])get(g2[a[i]],-1);
			get(g1[a[i]],1);
		}
		g2[a[i]]=g1[a[i]];
		g1[a[i]]=i;
		while(s[head].y==i) ans[s[head].num]=find(n)-find(s[head].x-1),head++;
	}
	for(i=1;i<=m;i++) print(ans[i]),putchar('\n');
}
posted @ 2020-04-22 08:29  275307894a  阅读(74)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end