19-10-15-W

暴力终于不跪了$ ext{QvQ}$

z总j结

考试开始看到几个大字:Day1

Happy~(××终于不用爆〇了哈哈哈哈!!)

开T1。一看,不是在线仙人球嵌套动态网络路径剖分优化的分支定界贪心剪枝启发式迭代加深人工智能搜索决策算法么……好!

码完一看,过不了大阳历……

关于大阳历,我是这么评价她的……

不给大阳历嫌他不给了,给了又过不了=.=

发现贪心错了。

于是马上……(×××的day1)

看T2。

发现是数学,研究一番,推了一番柿子,然后就弃了。

这时我有点慌了(开考$1h$啥都没打??)

于是马上看T3(?)

暴力好打$ ext{QvQ}$

打完T3回去想了下T1

码了一个$Theta(N^2log N)$的法子(全是在线仙人球嵌套动态网络路径剖分优化的分支定界贪心剪枝启发式迭代加深人工智能搜索决策算法)

然后T2的暴力也出来了。

最后是……

28
Miemeng 70
03:11:56
30
03:11:57
50
03:11:57
150
03:11:57

T1

法1

讲个我的$Theta(N^2log N)$

想到了让点找段,但是没来得及打。

于是我让段找点。

但是从左往右扫一定会死,因为贪心……

于是我想到可以维护段内的点数来贪。

从内部点数最少的段向更大的段贪。

每次修改都要重新计算和 sort 

交上去$70$

(话说为啥本地对拍一直WA

#include <algorithm>
#include <iostream>
#include <climits>
#include <cstring>
#include <cstdio>
#define N 222222

using namespace std;

struct Seg{
	int l,r;
	int pn;
}dse[N];
int dpo[N],sen,pon,ans=0;
bool is_del[N];
int findv(int val){
	return lower_bound(dpo+1,dpo+pon+1,val)-dpo;
}
inline bool CMP(const Seg &a,const Seg &b){
	return a.pn<b.pn;
}
int main(){
//	freopen("dream.in" ,"r",stdin);
	freopen("dream.out","w",stdout);
	scanf("%d%d",&sen,&pon);
	for(int i=1;i<=sen;i++)
		scanf("%d%d",&dse[i].l,&dse[i].r);
	for(int i=1;i<=pon;i++)
		scanf("%d",dpo+i);
	sort(dpo+1,dpo+pon+1);
	for(int i=1;i<=sen;i++){
		dse[i].pn=findv(dse[i].r+1)-findv(dse[i].l);
	}
	sort(dse+1,dse+sen+1,CMP);
	for(int i=1;i<=sen;i++){
//		cout<<dse[i].l<<" "<<dse[i].r<<" "<<dse[i].pn<<endl;
		int l=findv(dse[i].l),
			r=findv(dse[i].r+1);
		bool is_c=0;
//		cout<<"["<<dpo[l]<<","<<dpo[r]<<")"<<endl;
		if(l<r){
//			cout<<i<<" ++++ "<<endl;
			is_c=1;
			dpo[l]=INT_MAX;
			ans++;
		}
		if(is_c){
			sort(dpo+1,dpo+pon+1);
			for(int k=i+1;k<=sen;k++){
				dse[k].pn=findv(dse[k].r+1)-findv(dse[k].l);
			}
			sort(dse+i+1,dse+sen+1,CMP);
		}
	}
	printf("%d
",ans);
}

正解……

点找段,堆优化……

首先对于每一个懵点,从左到右扫,一定是能覆盖它且右端点更靠左的更优。

于是用堆优化这个过程。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

#define N 222222

using namespace std;

struct Seg{
	int l,r;
	friend bool operator < (const Seg &a,const Seg &b){
		return a.r>b.r;
	}
}seg[N];
int sen,pn;
void pour(priority_queue<Seg>s){
	puts("---------===VV===----------");
	while(!s.empty()){
		cout<<s.top().l<<" "<<s.top().r<<endl;
		s.pop();
	}
	puts("---------===^^===----------");
}
priority_queue<Seg>q;
int po[N],ans=0;
int main(){
	scanf("%d%d",&sen,&pn);
	for(int i=1;i<=sen;i++)
		scanf("%d%d",&seg[i].l,&seg[i].r);
	for(int i=1;i<=pn;i++)
		scanf("%d",po+i);
	sort(po+1,po+pn+1);
	sort(seg+1,seg+sen+1,[](const Seg &a,const Seg &b){return a.l<b.l;});
	int sid=1;
	for(int i=1;i<=pn;i++){
		while(sid<=sen && seg[sid].l<=po[i])q.push(seg[sid]),sid++;
		while(!q.empty() && q.top().r<po[i])q.pop();
		if(!q.empty() && q.top().l<=po[i] && po[i]<=q.top().r){
			ans++;
			q.pop();
		}
	}
	printf("%d
",ans);
}

T2

很显然(不会)的$dp$

T3

莫队直接过,$Theta(1)$转移一下就好了。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define N 222222

using namespace std;

struct Query{
	int l,r;
	int id;
}qs[N];
struct SR{
	int next,t;
}rs[2*N];
int pn,qn,
	fl[N],
	inp[N],
	ans[N],
	fa[N],
	ason[N],
	pl,
	nans,
	cnt=0;
bool isc[N];

inline bool CMP(const Query &a,const Query &b){
	return inp[a.l]==inp[b.l]?(inp[a.l]&1?a.r<b.r:a.r>b.r):inp[a.l]<inp[b.l];
}
void add(int f,int t){
	rs[cnt].t=t;
	rs[cnt].next=fl[f];
	fl[f]=cnt++;
}
void dfs(int k,int pre){
	for(int i=fl[k];i!=-1;i=rs[i].next){
		int t=rs[i].t;
		if(t!=pre){
			fa[t]=k;
			dfs(t,k);
		}
	}
}
void add(int id){
	ason[fa[id]]++;
	nans-=ason[id]+isc[fa[id]]-1;
	isc[id]=true;
}
void del(int id){
	ason[fa[id]]--;
	nans+=ason[id]+isc[fa[id]]-1;
	isc[id]=false;
}
int main(){
	int a,b;
	memset(fl,-1,sizeof fl);
	scanf("%d%d",&pn,&qn);pl=sqrt(pn)+1;
	for(int i=1;i<=pn;i++)
		inp[i]=(i-1)/pl+1;
	for(int i=1;i<pn;i++){
		scanf("%d%d",&a,&b);
		add(a,b);
		add(b,a);
	}
	dfs(1,0);
	for(int i=1;i<=qn;i++){
		scanf("%d%d",&qs[i].l,&qs[i].r);
		qs[i].id=i;
	}
	sort(qs+1,qs+qn+1,CMP);
	int l=1,r=1;
	add(1);
	for(int i=1;i<=qn;i++){
		while(l>=qs[i].l){
			l--;
			add(l);
		}
		while(r<=qs[i].r){
			r++;
			add(r);
		}
		while(l<qs[i].l){
			del(l);
			l++;
		}
		while(r>qs[i].r){
			del(r);
			r--;
		}
		ans[qs[i].id]=nans;
	}
	for(int i=1;i<=qn;i++)
		printf("%d
",ans[i]);
}
原文地址:https://www.cnblogs.com/kalginamiemeng/p/Exam20191015.html