BZOJ 4003

妈妈呀吓死我了再也不敢写斜堆了。。。。。。。。。。斜堆跑了9秒多,差点超时(我怀疑单点早超时了)

其实斜堆和左偏树比起来就少了一个变量和一行代码。

还是老老实实写左偏树算了。

这题嘛,维护若干个堆,堆里面是好多好多骑士,然后DFS一下,每次DFS的时候把每个点的子节点都merge过来,然后DFS完一个节点就把到达这个节点的渣渣骑士都干掉,顺便看一下他们经过了多少城池,同时把该节点(城池)的战绩更新一下。

这题过得我好虚啊……

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#define lc(x) heap[x].lc
#define rc(x) heap[x].rc
#define v(x) heap[x].v
#define a(x) heap[x].a
#define m(x) heap[x].m
#define d(x) heap[x].d
using namespace std;
const int N=300000+10;
typedef long long ll;
template<class T>void read(T& x){
	static char c;
	static bool f;
	for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
	for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
	if(f)x=-x;
}
struct Node{
	int lc,rc,d;
	ll v,a,m;
}heap[N];
void add_tag(int x,ll mul,ll add){
	if(!x)return;
	m(x)*=mul;
	a(x)=a(x)*mul+add;
	v(x)=v(x)*mul+add;
}
void down(int x){
	add_tag(lc(x),m(x),a(x));add_tag(rc(x),m(x),a(x));
	m(x)=1;a(x)=0;
}
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(v(x)>v(y))swap(x,y);
	down(x);down(y);
	rc(x)=merge(rc(x),y);
	if(d(rc(x))>d(lc(x)))swap(lc(x),rc(x));
	d(x)=d(rc(x))+1;
	return x;
}
struct Edge{int to,next;}e[N];
int head[N],cnt;
void ins(int u,int v){
	e[++cnt]=(Edge){v,head[u]};head[u]=cnt;
}
int die[N],get[N],fa[N],root[N],d[N],c[N];
ll def[N],mul[N],add[N];
void dfs(int u){
	die[u]=0;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].to;
		d[v]=d[u]+1;
		dfs(v);
		add_tag(root[v],mul[v],add[v]);
		root[u]=merge(root[u],root[v]);
	}
	while(root[u]&&v(root[u])<def[u]){
		down(root[u]);
		get[root[u]]=d[c[root[u]]]-d[u];
		root[u]=merge(lc(root[u]),rc(root[u]));
		die[u]++;
	}
}
int main(){
	int n,m;read(n);read(m);
	for(int i=1;i<=n;i++)read(def[i]);
	int kind;ll tmp;
	for(int i=2;i<=n;i++){
		read(fa[i]);read(kind);read(tmp);
		if(kind)mul[i]=tmp,add[i]=0;
		else mul[i]=1,add[i]=tmp;
		ins(fa[i],i);
	}
	for(int i=1;i<=m;i++){
		read(v(i));read(c[i]);
		m(i)=1;
		root[c[i]]=merge(root[c[i]],i);
	}
	dfs(1);
	while(root[1]){
		get[root[1]]=d[c[root[1]]]-d[1]+1;
		root[1]=merge(lc(root[1]),rc(root[1]));
	}
	for(int i=1;i<=n;i++)printf("%d\n",die[i]);
	for(int i=1;i<=m;i++)printf("%d\n",get[i]);
	return 0;
}
	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值