BZOJ1510: [POI2006]Kra-The Disks 二分+前缀和
BZOJ1535: [POI2005]Sza-Template 双向链表+KMP

BZOJ1528: [POI2005]sam-Toy Cars 贪心+线段树

shinbokuow posted @ Sep 18, 2015 07:07:10 PM in BZOJ with tags 贪心 线段树 , 642 阅读

 

题解:

万物皆线段树系列。。。

脑补了一个贪心是每次删除玩具时,删除下一次出现最靠后的那个玩具。

但是不会证明,也找不出反例的样子。。。

随便维护维护就过了。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int getc(){
	static const int L=1<<15;
	static char buf[L],*S=buf,*T=buf;
	if(S==T){
		T=(S=buf)+fread(buf,1,L,stdin);
		if(S==T)
			return EOF;
	}
	return*S++;
}
int getint(){
	int c;
	while(!isdigit(c=getc()));
	int x=c-'0';
	while(isdigit(c=getc()))
		x=(x<<1)+(x<<3)+c-'0';
	return x;
}

typedef pair<int,int> pii;
#define mp make_pair
struct SegmentTree{
	pii mx[262144];
	int M;
	void init(int _siz){
		for(M=1;M<(_siz+2);M<<=1);
		for(int i=1;i<(M<<1);++i)
			mx[i]=mp(-1,0);
		for(int i=1;i<=_siz;++i)
			mx[M+i].second=i;
	}
	void modify(int x,int v){
		for(mx[x+=M].first=v,x>>=1;x;x>>=1)
			mx[x]=max(mx[x<<1],mx[x<<1^1]);
	}
	pii query(int tl,int tr){
		pii ans=mp(-1,0);
		for(tl+=M-1,tr+=M+1;tl^tr^1;tl>>=1,tr>>=1){
			if(~tl&1)
				ans=max(ans,mx[tl^1]);
			if(tr&1)
				ans=max(ans,mx[tr^1]);
		}
		return ans;
	}
}Seg;

#define N 100010
#define M 500010
int last[N],nxt[M],a[M];

bool ok[N];
int main(){
#ifndef ONLINE_JUDGE
	freopen("tt.in","r",stdin);
#endif
	int n=getint(),m=getint(),q=getint(),i,j;
	for(i=1;i<=q;++i)
		a[i]=getint();
	for(i=q;i>=1;--i){
		nxt[i]=last[a[i]]==0?q+1:last[a[i]];
		last[a[i]]=i;
	}
	int cnt=0,ans=0;
	pii get;
	Seg.init(n);
	for(i=1;i<=q;++i){
		if(!ok[a[i]]){
			++ans;
			if(cnt==m){
				get=Seg.query(1,n);
				ok[get.second]=0;
				Seg.modify(get.second,-1);
			}
			else
				++cnt;
			ok[a[i]]=1;
		}
		Seg.modify(a[i],nxt[i]);
	}
	cout<<ans<<endl;
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter