2743: [HEOI2012]採花

Description

蕭芸斕是Z國的公主,平時的一大愛好是採花。
今天天氣晴朗,陽光明媚,公主清晨便去了皇宮中新建的花園採花。花園足夠大,容納了n朵花,花有c種顏色(用整數1-c表示),且花是排成一排的,以便於公主採花。公主每次採花後會統計採到的花的顏色數,顏色數越多她會越高興!同時,她有一癖好,她不允許最後自己採到的花中,某一顏色的花只有一朵。爲此,公主每採一朵花,要麼此前已採到此顏色的花,要麼有相當正確的直覺告訴她,她必能再次採到此顏色的花。由於時間關係,公主只能走過花園連續的一段進行採花,便讓女僕福涵潔安排行程。福涵潔綜合各種因素擬定了m個行程,然後一一向你詢問公主能採到多少朵花(她知道你是編程高手,定能快速給出答案!),最後會選擇令公主最高興的行程(爲了拿到更多獎金!)。

Input


 第一行四個空格隔開的整數n、c以及m。接下來一行n個空格隔開的整數,每個數在[1, c]間,第i個數表示第i朵花的顏色。接下來m行每行兩個空格隔開的整數l和r(l ≤ r),表示女僕安排的行程爲公主經過第l到第r朵花進行採花。

Output

 
m行,每行一個整數,第i個數表示公主在女僕的第i個行程中能採到的花的顏色數。
題解:
離線+樹狀數組
這題跟之前做的某一題有點像,忘記是哪道了。
求出每個顏色下一個出現的位置,
然後,對於當前枚舉到的位置,nex[i]-1,nex[nex[i]]+1,
記得把詢問排序。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000010;
int n,c,m;
int a[N],next[N],pre[N];
struct node{
	int l,r,id;
}sa[N];
int ans[N];
bool cmp(node x,node y)
{
	return x.l<y.l;
}
int sum[N];
int lowbit(int x)
{
	return x&(-x);
}
int query(int x)
{
	int yu=0;
	for(int i=x;i>=1;i-=lowbit(i))
	yu+=sum[i];
	return yu;
}
void add(int x,int y)
{
	for(int i=x;i<=n;i+=lowbit(i))
	sum[i]+=y;
}
bool v[N];
int main()
{
	scanf("%d%d%d",&n,&c,&m);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	memset(pre,0,sizeof(pre));
	memset(next,0,sizeof(next));
	memset(sum,0,sizeof(sum));
	for(int i=n;i>=1;i--)
	{
		if(pre[a[i]]) next[i]=pre[a[i]];
		pre[a[i]]=i;
	}

	for(int i=1;i<=m;i++)
	scanf("%d%d",&sa[i].l,&sa[i].r),sa[i].id=i;
	sort(sa+1,sa+1+m,cmp);
	for(int i=1;i<=n;i++)
	{
		if(!v[a[i]]) 
		{
			
			if(next[i])add(next[i],1);v[a[i]]=1;
		}
	}//printf("!");
	int j=0;
	for(int i=1;i<=m;i++)
	{	
		while(j<sa[i].l)
		{
		    if(next[j])
			{
				add(next[j],-1);
		    if(next[next[j]])add(next[next[j]],1);
			}
		    j++;
		}
	    ans[sa[i].id]=query(sa[i].r);
	}
	for(int i=1;i<=m;i++)
	printf("%d\n",ans[i]);
}


發佈了159 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章