首页 > 其他分享 >9.27比赛记录

9.27比赛记录

时间:2022-09-27 16:14:45浏览次数:54  
标签:ch 9.27 比赛 记录 int ll root 节点 define

T1

不会,再见。/fn

T2

题意

有 \(n\) 个奶牛排成一列,每次队头的牛都会插到第倒数 \(c_i\) 个位置上,问有多少个牛无法到达第一位。

思路

是道很厉害的二分。可惜赛时没打出来。

不难发现它是具有单调性的,如果有 \(i\) 头牛可以拿到那么 \(i-1\) 条牛一定可以拿到(废话)。

这启发我们想到二分答案。

check 是好写的,判断一下前 \(mid\) 个是否可以全取到即可。

时间复杂度 \(O(n \log n)\)。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define pb(x) push_back(x)
#define lowbit(x) x&-x
using namespace std;
const int N=1e5+10;
ll ans;
int n,m,T,a[N],q[N];
inline int read(){
	int s=0,f=0;
	char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch<='9'&&ch>='0') s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return f?-s:s;
}
inline bool check(int mid){
	memset(q,0,sizeof(q));
	for(register int i=1;i<=mid;++i) q[a[i]]++;
	for(register int i=1;i<=n;++i) q[i]+=q[i-1];
	for(register int i=1;i<=n;++i) if(q[i-1]<i&&q[i]>=i) return 0;
	return 1;
}
int main(){
	n=read();
	for(register int i=1;i<=n;++i) a[i]=n-read();
	int l=0,r=n;
	while(l<r){
		int mid=(l+r)>>1;
		if(check(mid)) l=mid+1;
		else r=mid;
	}
	printf("%d",n-l);
	return 0;
}

T3

不会,看上去是大模拟,爬。

T4

不会 \(\text{dp}\)。

T5

唯一赛时做出来的一道。/ll

题意

给定一棵 \(n\) 个节点的无根树,每个叶子节点都视为一个出入口,有一只奶牛想要从出入口逃走,但农夫们不想要这样,他们可以派人守在出入口。

每一个时间内,奶牛和农夫都可以移动到相邻的节点上,并且农夫知道奶牛会如何移动,问对于每一个起始 \(i\),农夫们最少需要多少人才能不让奶牛逃脱?

思路

听说正解是点分治啊。很厉害。但暴力草过去了是怎么回事呢。/yiw

首先发现答案可以由两部分构成,一个是直接从子树中的叶子结点润掉,另一个就是先润到父亲节点再走。

直接在子树中的答案是简单的,我们考虑对于一个叶子节点,怎样才能不放人就守住该节点。

我们只需要保证存在另一个存在农夫的叶子结点 \(x\),它与该节点的距离小于根节点到该点的距离即可。可以用一种类似于分治的怪方法写完。

然后考虑要走到父亲的答案。

我们希望的是让农民数越少越好,所以在离当前节点最近的叶子节点上面放一定是优的。

然后用一个类似前缀 \(\max\) 的东西记录下从 \(1\) 到当前节点的链上面离当前节点最近的叶子即可。

复杂度不太好算,极限数据可以卡到 \(3s\) 左右,但是可以通过本题。

代码

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define pb(x) push_back(x)
#define lowbit(x) x&-x
using namespace std;
const int N=1e5+10;
struct node{
	int to,nxt,sz,us;
}a[N<<1];
int n,m,T,head[N],cnt;
int nxt[N],d[N],p[N],ans[N],f[N],rd[N],pre[N],pd[N],pp[N],maxn[N];
inline int read(){
	int s=0,f=0;
	char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch<='9'&&ch>='0') s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return f?-s:s;
}
inline void add(int from,int to){
	a[++cnt]=(node){to,head[from],0,1};
	head[from]=cnt;
}
void dfs(int x,int fa){
	d[x]=d[fa]+1;
	f[x]=fa;
	p[x]=1e9;
	int tot=0,id;
	for(register int i=head[x];i;i=a[i].nxt){
		int to=a[i].to;
		if(to==fa) continue;
		dfs(to,x);
		++tot;
		id=to;
		a[i].sz=nxt[to];
		if(p[to]+1<p[x]){
			pp[x]=p[x];
			p[x]=p[to]+1;
			maxn[x]=to;
		}else if(p[to]+1<pp[x]) pp[x]=p[to]+1;
	}
	if(tot==1) nxt[x]=nxt[id];
	else nxt[x]=x,pd[x]=1;
	if(p[x]==1e9){
		p[x]=0;
	}
}
int calc(int x,int de){
	if(p[x]<=de) return 1;
	int res=0;
	for(register int i=head[x];i;i=a[i].nxt){
		int to=a[i].to;
		if(!a[i].us||f[x]==to) continue;
		res+=calc(nxt[to],de+d[nxt[to]]-d[x]);
	}
	return res;
}
void calcson(int x,int fa){
	if(pd[fa]) pre[x]=fa;
	else pre[x]=pre[fa];
	for(register int i=head[x];i;i=a[i].nxt){
		int to=a[i].to;
		if(to==fa) continue;
		int q=a[i].sz;
		ans[x]+=calc(q,d[q]-d[x]);
		calcson(to,x);
	}
}
int sv[N],sid[N];
void calcfa(int x,int fa){
	if(fa!=0){
		if(p[fa]==1){
			ans[x]++;
		}else{
			int now=pre[x];
			while(now!=0){
				if(sv[now]+d[sid[now]]+d[now]-d[sid[now]]<=d[x]-d[now]){
					ans[x]++;
					break;
				}
				ans[x]+=calc(now,d[x]-d[now]);
				now=pre[now];
			}
		}
	}
	sv[x]=1e9,sid[x]=-1;
	for(register int i=head[x];i;i=a[i].nxt){
		int to=a[i].to;
		if(to==fa) continue;
		a[i].us=0;
		if(to==maxn[x]){
			if(pp[x]-d[x]<sv[fa]){
				sv[x]=pp[x]-d[x];
				sid[x]=x;
			}else{
				sv[x]=sv[fa];
			}
		}else{
			if(p[x]-d[x]<sv[fa]){
				sv[x]=p[x]-d[x];
				sid[x]=x;
			}else{
				sv[x]=sv[fa];
			}
		}
		calcfa(to,x);
		sv[x]=1e9,sid[x]=-1;
		a[i].us=1;
	}
}
int main(){
	n=read();
	int root=1;
	for(register int i=1;i<n;++i){
		int u=read(),v=read();
		add(u,v),add(v,u);
		++rd[u],++rd[v];
		if(rd[u]>=2) root=u;
		if(rd[v]>=2) root=v;
	}
	d[0]=-1;
	dfs(root,0);
	sv[0]=1e9;
	calcson(root,0);
	calcfa(root,0);
	for(register int i=1;i<=n;++i) printf("%d\n",ans[i]);
	return 0;
}

标签:ch,9.27,比赛,记录,int,ll,root,节点,define
From: https://www.cnblogs.com/kqwlp/p/16734867.html

相关文章