P4113 [HEOI2012]采花

题面

萧薰儿是古国的公主,平时的一大爱好是采花。

今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。

花园足够大,容纳了 \(n\) 朵花,共有 \(c\) 种颜色,用整数 \(1 \sim c\) 表示。且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴。同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。

由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了 \(m\) 个行程,然后一一向你询问公主能采到的花共有几种不同的颜色。

思路

暴力

暴力时间复杂度为 \(O(nm)\),可以水50分。

// O(nm)

#include<bits/stdc++.h>
using namespace std;

const int SIZE = 1e6+5;
int n,c,m;
int flower[SIZE];
int bucket[SIZE];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>c>>m;
	for(int i=1;i<=n;i++){
		cin>>flower[i];
	}
	while(m--){
		memset(bucket,0,sizeof(bucket));
		int l,r,ans=0;
		cin>>l>>r;
		for(int i=l;i<=r;i++){
			bucket[flower[i]]++;
		}
		for(int i=1;i<=c;i++){
			if(bucket[i]>1){
				ans++;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

基础莫队

本题和小B的询问很像。

莫队复杂度为 \(O(m \sqrt{n})\)

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int SIZE = 2e6+5;
int times[SIZE];int a[SIZE];int ans[SIZE];
int tans;
int block;
int n,m,k;
int ans1=1,ans2=0;

struct query{
	int l,r,id;
	bool operator<(const query y) const {
		if((l-1)/block==(y.l-1)/block) {
			return r<y.r;
		}
		return l/block<y.l/block;
	}
} querys[SIZE];

void add(int x){
	times[x]++;
	if(times[x]==2){
		++tans;
	}
}

void remove(int x){
	times[x]--;
	if(times[x]==1){
		--tans;
	}
}

void modui(int l,int r,int i){
	while(ans1>l){
		ans1--;
		add(a[ans1]);
	}
	while(ans2<r){
		ans2++;
		add(a[ans2]);
	}
	while(ans1<l){
		remove(a[ans1]);
		ans1++;
	}
	while(ans2>r){
		remove(a[ans2]);
		ans2--;
	}
	ans[querys[i].id]=tans;
}

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-48;ch=getchar();}
	return x*f;
}

signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	n=read(),m=read(),k=read();
	swap(m,k);
	block=sqrt(n);
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<=m;i++){
		querys[i].l=read();
		querys[i].r=read();
		querys[i].id=i;
	}
	sort(querys+1,querys+m+1);
	for(int i=1;i<=m;i++){
		modui(querys[i].l,querys[i].r,i);
	}
	for(int i=1;i<=m;i++){
		cout<<ans[i]<<endl;
	}
	return 0;
}

可以水 100 分。

莫队+奇偶化排序

可以优化到133分。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int SIZE = 2e6+5;
int times[SIZE];int a[SIZE];int ans[SIZE];
int tans;
int unit=1314;
int n,m,k;
int ans1=1,ans2=0;

struct query{
	int l,r,id;
	bool operator<(const query &x) const {
    if (l / unit != x.l / unit) return l < x.l;
    if ((l / unit) & 1)
      return r < x.r;  
    return r > x.r;
  }
} querys[SIZE];

void add(int x){
	times[x]++;
	if(times[x]==2){
		++tans;
	}
}

void remove(int x){
	times[x]--;
	if(times[x]==1){
		--tans;
	}
}

void modui(int l,int r,int i){
	while(ans1>l){
		ans1--;
		add(a[ans1]);
	}
	while(ans2<r){
		ans2++;
		add(a[ans2]);
	}
	while(ans1<l){
		remove(a[ans1]);
		ans1++;
	}
	while(ans2>r){
		remove(a[ans2]);
		ans2--;
	}
	ans[querys[i].id]=tans;
}

namespace IO{
	const int SIZE=1<<21;
	static char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=oS+SIZE-1;
    int qr;
    char qu[55],c;
    bool f;
	#define getchar() (IO::iS==IO::iT?(IO::iT=(IO::iS=IO::ibuf)+fread(IO::ibuf,1,IO::SIZE,stdin),(IO::iS==IO::iT?EOF:*IO::iS++)):*IO::iS++)
	#define putchar(x) *IO::oS++=x,IO::oS==IO::oT?flush():0
	#define flush() fwrite(IO::obuf,1,IO::oS-IO::obuf,stdout),IO::oS=IO::obuf
	#define puts(x) IO::Puts(x)
	template<typename T>
    inline void read(T&x){
    	for(f=1,c=getchar();c<48||c>57;c=getchar())f^=c=='-';
    	for(x=0;c<=57&&c>=48;c=getchar()) x=(x<<1)+(x<<3)+(c&15); 
    	x=f?x:-x;
    }
    template<typename T>
    inline void write(T x){
        if(!x) putchar(48); if(x<0) putchar('-'),x=-x;
        while(x) qu[++qr]=x%10^48,x/=10;
        while(qr) putchar(qu[qr--]);
    }
    inline void Puts(const char*s){
    	for(int i=0;s[i];i++)
			putchar(s[i]);
		putchar('\n');
	}
	struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}
using IO::read;
using IO::write;

signed main(){
   read(n);read(m);read(k);
   swap(m,k);
	for(int i=1;i<=n;i++){
		read(a[i]);
	}
	for(int i=1;i<=m;i++){
		read(querys[i].l);
		read(querys[i].r);
		//querys[i].r=read();
		querys[i].id=i;
	}
	sort(querys+1,querys+m+1);
	for(int i=1;i<=m;i++){
		modui(querys[i].l,querys[i].r,i);
	}
	for(int i=1;i<=m;i++){
		write(ans[i]);
		putchar('\n');
	}
	return 0;
}

正解等待中……

posted @ 2022-03-19 14:04  蒟蒻xiezheyuan  阅读(41)  评论(0编辑  收藏  举报