noip模拟17
\(\color{white}{\mathbb{霞光划破暗淡天际,月影彷徨,鸡鸣仿佛,冀之以继往开来,名之以:黎明}}\)
今天似乎取得了有史以来最好的成绩~

前两名都 A 掉了 \(t3\),然鹅 \(t3\) 上去就被我弃了……
前两天部分分都写得比较顺利
\(t1\) 一眼以为 \(bitset\) 裸题,开了 \(6e4 * 6e4\) 直接自信提交,后来一算才发现空间炸了
但是不记得一位 \(bitset\) 是多大,以为和 \(bool\) 一样,只能开 \(10^4 * 10^4\),没敢打另外 20% 的部分分,暴挂20分
\(t2\) 网络流板子忘得差不多了,口胡了还几次才过了样例
A. 世界线
读懂题很快就能看出来是 \(bitset\),但是空间比较卡
首先,\(bitset\) 是每8位占用一个字节,一次运算复杂度为 \(n/32\)
那么其实前 \(60%\) 都是可以轻松水过去的
发现最后两个点的理论空间都比能开下的 \(bitset\) 大一倍,那么可以采用把所有点分成两部分的方式统计,\(bitset\) 只开一半,第一次统计所有点能到达的 \(\le n/2\) 的点的个数,再来一次统计能到达的 \(>n/2\) 的点的个数,直接相加即可
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=6e4+5;
const int maxm=1e6+5;
int n,m,deg[maxn],x,y,hd[maxn],cnt,limit,out[maxn];
bitset<maxn/2>vis[maxn];
long long ans;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*f;
}
struct Edge{
	int nxt,to;
}edge[maxm];
void add(int u,int v){
	edge[++cnt].nxt=hd[u];
	edge[cnt].to=v;
	hd[u]=cnt;
	return ;
}
void topsort(int op){
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(!deg[i])q.push(i);
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=hd[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			vis[v]|=vis[u];
			if(!(--deg[v])){
				q.push(v);
			}
		}
	}
	return ;
}
int main(){
	n=read();
	m=read();
	for(int i=1;i<=m;i++){
		x=read();
		y=read();
		deg[x]++;
		add(y,x);
	}
	for(int i=1;i<=n;i++){
		ans-=deg[i]+1;
		out[i]=deg[i];
	}
	limit=n/2;
	for(int i=1;i<=limit;i++){
		vis[i][i]=1;
	}
	topsort(0);
	for(int i=1;i<=n;i++){
		ans+=vis[i].count();
//		cout<<vis[i].count()<<endl;
		vis[i].reset();
		deg[i]=out[i];
	}
//	vis.reset();
	for(int i=limit+1;i<=n;i++){
		vis[i][i-limit]=1;
	}
	topsort(1);
	for(int i=1;i<=n;i++){
//		cout<<vis[i].count()<<" ";
		ans+=vis[i].count();
	}
	cout<<ans;
	return 0;
}
/*
5 5
1 2
1 3
2 3
3 4
4 5
*/
B. 时间机器
说实话考场上没有认真看懂题,光用网络流水了一下居然拿到了70分
这道题正解贪心
考虑所有元件和节点按左端点第一关键字右端点第二关键字排序后,那么右端点靠左的元件越容易用不上,所以尽可能优先选取右端点靠左的元件
那么对于一个节点拥有一个左右端点满足条件的候选集合,考虑左端点对于后面的节点都是可用的,但是右端点可能会被淘汰掉,那么就选择右端点最靠左的一个元件进行匹配
这个可以用 \(set\) 实现
注意这道题一开始一直被卡常,后来发现 \(s.lower\_bound(xxx)\) 比 \(lower\_bound(s.begin(),s.end(),xxx)\) 快好多
代码实现
#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int maxn=1e6+5;
int t,n,m,tp;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*f;
}
struct Th{
	int l,r,num;
}a[maxn],b[maxn];
struct Node{
	int fi;
	mutable int se;
	Node(int x=0,int y=0):fi(x),se(y){}
};
bool operator < (const Node &x,const Node &y){
	return x.fi!=y.fi?x.fi<y.fi:x.se<y.se;
}
multiset<Node>s;
bool operator < (const Th &x,const Th &y){
	return x.l==y.l?x.r<y.r:x.l<y.l;
}
void solve(){
	tp=1;
	for(int i=1;i<=n;i++){
		while(tp<=m&&b[tp].l<=a[i].l){
			s.insert(Node(b[tp].r,b[tp].num));
			tp++;
		}
		while(a[i].num){
			multiset<Node>::iterator it=s.lower_bound(Node(a[i].r,0));
			if(it==s.end()){
				puts("No");
				return ;
			}
			if(a[i].num < it->se){
				it->se -= a[i].num;
				break;
			}
			a[i].num-= it->se;
			s.erase(it);
		}
	}
	puts("Yes");
}
signed main(){
	t=read();
	while(t--){
		n=read();
		m=read();
		for(int i=1;i<=n;i++){
			a[i].l=read();
			a[i].r=read();
			a[i].num=read();
		}
		for(int i=1;i<=m;i++){
			b[i].l=read();
			b[i].r=read();
			b[i].num=read();
		}
		sort(a+1,a+n+1);
		sort(b+1,b+m+1);
		s.clear();
		solve();
	}
	return 0;
}
/*
3
2 2
1 2 2
1 2 1
1 2 1
1 2 2
2 2
1 4 2
3 5 1
1 4 2
2 5 1
3 2
1 3 1
2 4 1
3 5 1
1 3 2
2 5 1
*/
C. weight
考完试 cyh 说和题单上的 Mst 这道题基本上是一样的,真后悔当时没看这道题
首先把最小生成树建出来,然后树边和非树边分别讨论
如果是非树边,那么答案为生成树上两端点路径上边权最大值 -1
如果是树边,则是所有和这条边有关的非树边的最小值 -1
可以采用树剖,每条非树边查询一次修改一次即可
cyh 的LCT理论复杂度少一个 \(log\),也非常好维护
注意判不在连通块里的边(可以用并查集判断),树剖需要边化点,更新时不能选上面的那个点
于是一直调一直改写了将近300行……
代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
const int maxm=4e5+5;
//const int inf=
int n,m,ans[maxn],x,y,w,op;
int read(){
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		x=x*10+ch-48;
		ch=getchar();
	}
	return x*f;
}
namespace p2{
	int hd[maxn],cnt,cnt1,re[maxn],fa[maxn],tot,id[maxn],pa[maxn],siz[maxn],son[maxn],dep[maxn],tp[maxn],val[maxn];
	struct Edge{
		int nxt,to,val,id;
	}edge[maxm];
	void add(int u,int v,int w,int num){
		edge[++cnt].nxt=hd[u];
		edge[cnt].to=v;
		edge[cnt].val=w;
		edge[cnt].id=num;
		hd[u]=cnt;
		return ;
	}
	struct Ch{
		int from,to,id,val;
	}link[maxm];
	void make(int u,int v,int w,int num){
		link[++cnt1].to=v;
		link[cnt1].from=u;
		link[cnt1].val=w;
		link[cnt1].id=num;
		return ;
	}
	void dfs(int u){
//		cout<<u<<" "<<endl;
		siz[u]=1;
		for(int i=hd[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(v==fa[u])continue;
			dep[v]=dep[u]+1;
			fa[v]=u;
			val[v]=edge[i].val;
			pa[v]=edge[i].id;
//			cout<<"hhh "<<v<<" "<<pa[v]<<endl;
			dfs(v);
			siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])son[u]=v;
		}
		return ;
	}
	void dfs1(int u,int top){
		tp[u]=top;
		id[u]=++tot;
		re[tot]=u;
//		cout<<u<<" ";
		if(son[u])dfs1(son[u],top);
		for(int i=hd[u];i;i=edge[i].nxt){
			int v=edge[i].to;
			if(v==fa[u]||v==son[u])continue;
			dfs1(v,v);
		}
		return ;
	}
	struct Seg{
		int l,r,mx,lazy;
	}t[maxn*4];
	void update(int p){
		t[p].mx=max(t[p<<1].mx,t[p<<1|1].mx);
		return ;
	}
	void build(int p,int l,int r){
		t[p].l=l;
		t[p].r=r;
		t[p].lazy=0x3f3f3f3f;
		if(l==r){
			t[p].mx=val[re[l]];
//			cout<<"kkk "<<l<<" "<<val[id[l]]<<endl;
			return ;
		}
		int mid=l+r>>1;
		build(p<<1,l,mid);
		build(p<<1|1,mid+1,r);
		update(p);
		return ;
	}
	int ask(int p,int l,int r){
		if(l>r)return 0;
		if(t[p].l>=l&&t[p].r<=r)return t[p].mx;
		int mx=0;
		int mid=t[p].l+t[p].r>>1;
		if(l<=mid)mx=ask(p<<1,l,r);
		if(r>mid)mx=max(mx,ask(p<<1|1,l,r));
		return mx;
	}
	int ques(int x,int y){
		int mx=0;
//		cout<<"hhh "<<endl;
		while(tp[x]!=tp[y]){
			if(dep[tp[x]]<dep[tp[y]])swap(x,y);
//			cout<<"ppp "<<id[tp[x]]<<" "<<id[x]<<endl;
			mx=max(mx,ask(1,id[tp[x]],id[x]));
			x=fa[tp[x]];
		}
//		cout<<mx<<endl;
		if(dep[x]>dep[y])swap(x,y);
//		cout<<"ppp "<<id[x]+1<<" "<<id[y]<<endl;
		mx=max(mx,ask(1,id[x]+1,id[y]));
//		cout<<id[x]<<" "<<id[y]<<endl;
		return mx;
	}
	void ch(int p,int l,int r,int w){
		if(l>r)return ;
		if(t[p].l>=l&&t[p].r<=r){
			t[p].lazy=min(t[p].lazy,w);
			return ;
		}
		int mid=t[p].l+t[p].r>>1;
		if(l<=mid)ch(p<<1,l,r,w);
		if(r>mid)ch(p<<1|1,l,r,w);
		return ;
	}
	void change(int x,int y,int w){
		while(tp[x]!=tp[y]){
			if(dep[tp[x]]<dep[tp[y]])swap(x,y);
			ch(1,id[tp[x]],id[x],w);
			x=fa[tp[x]];
		}
//		cout<<mx<<endl;
		if(dep[x]>dep[y])swap(x,y);
		ch(1,id[x]+1,id[y],w);
		return ;
	}
	void spread(int p){
		if(t[p].l==t[p].r){
//			cout<<t[p].l<<" "<<re[t[p].l]<<" "<<pa[re[t[p].l]]<<endl;
			ans[pa[re[t[p].l]]]=t[p].lazy;
			return ;
		}
		t[p<<1].lazy=min(t[p<<1].lazy,t[p].lazy);
		t[p<<1|1].lazy=min(t[p<<1|1].lazy,t[p].lazy);
		spread(p<<1);
		spread(p<<1|1);
		return ;
	}
	void start(){
		dfs(1);
		pa[1]=m+1;
		dfs1(1,1);
		build(1,1,n);
//		for(int i=1;i<=n;i++){
//			cout<<pa[i]<<endl;
//		}
//		cout<<endl;
//		cout<<"hhh ";
		for(int i=1;i<=cnt1;i++){
			int x=link[i].from;
			int y=link[i].to;
//			cout<<link[i].id<<" "<<x<<" "<<y<<" "<<link[i].val<<endl;
			ans[link[i].id]=ques(x,y);
//			flag[link[i].id];
//			cout<<ans[link[i].id]<<endl;
//			cout<<link[i].id<<" "<<ans[link[i].id]<<endl;
			change(x,y,link[i].val);
		}
		spread(1);
		return ;
	}
}
namespace p1{
	int hd[maxn],cnt,fa[maxn];
	struct Edge{
		int nxt,to,from,val,id;
	}edge[maxm],edge1[maxm];
	void add(int u,int v,int w){
		edge[++cnt].nxt=hd[u];
		edge[cnt].to=v;
		edge[cnt].from=u;
		edge[cnt].val=w;
		return ;
	}
	bool cmp(Edge a,Edge b){
		return a.val<b.val;
	}
	int find(int x){
		return fa[x]==x?x:fa[x]=find(fa[x]);
	}
	void kruscal(){
		sort(edge+1,edge+m+1,cmp);
		for(int i=1;i<=n;i++){
			fa[i]=i;
		}
		for(int i=1;i<=m;i++){
			int u=edge[i].from;
			int v=edge[i].to;
			x=find(u);
			y=find(v);
			if(x!=y){
				fa[x]=y;
//				cout<<u<<" "<<v<<" "<<edge[i].val<<" "<<edge[i].id<<endl;
				p2::add(u,v,edge[i].val,edge[i].id);
				p2::add(v,u,edge[i].val,edge[i].id);
			}
			else{
//				cout<<u<<" "<<v<<" "<<edge[i].val<<" "<<edge[i].id<<endl;
				p2::make(u,v,edge[i].val,edge[i].id);
			}
		}
		return ;
	}
}
namespace p3{
	int fa[maxn],tot,tot1,idx[maxn];
	int find(int x){
		return fa[x]==x?x:fa[x]=find(fa[x]);
	}
	void pd(){
		for(int i=1;i<=n;i++){
			fa[i]=i;
		}
		for(int i=1;i<=m;i++){
			int x=p1::edge[i].from;
			int y=p1::edge[i].to;
			x=find(x);
			y=find(y);
			if(x!=y)fa[x]=y;
		}
		for(int i=1;i<=m;i++){
			p1::edge1[i]=p1::edge[i];
//			cout<<find(p1::edge[i].from)<<" "<<find(1)<<endl;
			if(find(p1::edge[i].from)!=find(1)&&find(p1::edge[i].to)!=find(1)){
				ans[p1::edge[i].id]=1;
//				cout<<"ppp "<<p1::edge[i].id<<endl;
				tot++;
			}
			else idx[++tot1]=i;
		}
		p1::cnt=0;
		memset(p1::hd,0,sizeof p1::hd);
		for(int i=1;i<=tot1;i++){
			p1::add(p1::edge1[idx[i]].from,p1::edge1[idx[i]].to,p1::edge1[idx[i]].val);
			p1::edge[p1::cnt].id=p1::edge1[idx[i]].id;
		}
		m=tot1;
	}
}
int main(){
//	freopen("c.in","r",stdin);
//	freopen("c.out","w",stdout);
	n=read();
	m=read();
	op=read();
	for(int i=1;i<=m;i++){
		x=read();
		y=read();
		w=read();
		p1::add(x,y,w);
		p1::edge[p1::cnt].id=i;
	}
//	cout<<"hhh ";
//	p3::tot1=m;
	p3::pd();
//	cout<<"ppp "<<m<<endl;
//	cout<<"hhh ";
//	for(int i=1;i<=m;i++){
//		cout<<p1::edge[i].from<<" "<<p1::edge[i].to<<" "<<p1::edge[i].val<<" "<<p1::edge[i].id<<endl;
//	}
	p1::kruscal();
//	cout<<"hhh ";
	p2::start();
	for(int i=1;i<=p3::tot+p3::tot1;i++){
		if(ans[i]==0x3f3f3f3f)printf("-1 ");
		else printf("%d ",ans[i]-1);
	}
	return 0;
}
/*
5 4 0
4 5 2
1 2 1
2 3 2
3 1 3
*/
\(\color{white}{\mathbb{困于心,衡于虑,而后作}}\)
noip模拟17的更多相关文章
- NOIP模拟17.9.21
		
NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...
 - NOIP模拟17.9.22
		
NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥
 - NOIP模拟 17.8.20
		
NOIP模拟17.8.20 A.阶乘[题目描述]亲爱的xyx同学正在研究数学与阶乘的关系,但是他喜欢颓废,于是他就制作了一个和阶乘有关系的数学游戏:给出两个整数 n,m,令 t = !n,每轮游戏的流 ...
 - NOIP模拟 17.8.18
		
NOIP模拟17.8.18 A.小菜一碟的背包[题目描述]Blice和阿强巴是好朋友但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习阿强巴有 n头奶牛,每头奶牛每天可以产一定量的奶,同时也 ...
 - NOIP模拟 17.8.15
		
NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...
 - NOIP模拟 17.8.17
		
NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...
 - NOIP模拟 17.8.16
		
NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...
 - NOIP模拟 17.8.14
		
NOIP模拟17.8.14 (天宇哥哥考察细心程度的题) [样例解释]如果删去第一个 1:在[3,1,2]中有 3 个不同的数如果删去 3:在[1,1,2]中有 2 个不同的数如果删去第二个 1:在[ ...
 - NOIP模拟 17.9.28
		
公交车[问题描述]市内有
 - Noip模拟17 2021.7.16
		
我愿称这场考试为STL专练 T1 世界线 巧妙使用$bitset$当作vis数组使用,内存不会炸,操作还方便,的确是极好的. 但是这个题如果不开一半的$bitset$是会炸内存的,因为他能开得很大,但 ...
 
随机推荐
- Centos 7 安装mysql5.7 nginx tomcat
 - Linux各目录及每个目录的详细介绍总结
			
Linux各目录及每个目录的详细介绍 [常见目录说明] 目录 /bin 存放二进制可执行文件(ls,cat,mkdir等),常用命令一般都在这里. /etc 存放系统管理和配置文件 /home 存放所 ...
 - Windows影子用户创建与3389连接
			
#当获得一条shell后,可以创建一个影子用户,通过影子用户可以行驶正常用户的所有权限与功能,并且只可在注册表中被检测出来---(应急响应注册表很重要) 1.首先需要拥有权限创建一个Administr ...
 - python语法入门
			
程序=数据+功能 我们学习编程语言的目的是为了控制计算机能够像人一样去做事 所以说,编程语言中出现的所有的语法都是为了控制计算机能够像人一样去做xxx事 一.注释: 1 ...
 - 为什么不建议使用WordPress呢?
			
程序过于注重扩展性与动态配置解析,导致执行流程中包含大量的钩子.判断.文件加载等操作,导致执行效率偏低,对服务器要求较高.对系统的开销,尤其是CPU等部分消耗较大,据观察,单个请求在腾讯云s1主机单核 ...
 - Java编程中经典语句收录
			
1.spring系列:约定优于配置(习惯大于配置): 2.Java:一次编译,处处运行 3.Unix:没有消息就是好消息
 - 十六进制转十进制 BASIC-12
			
十六进制转十进制 代码 import java.math.BigInteger; import java.util.Scanner; /* * 从键盘输入一个不超过8位的正的十六进制数字符串, * 将 ...
 - 直流电机、减速器、编码器与TB6612FNG知识整理
			
之前把MPU6050的相关知识了解了一下,可以做到测量欧拉角,在平衡小车的开发中需要测量小车的倾角来调整小车姿态.接下来该学习小车的电机驱动部分了,这里整理一下直流电机.减速器.编码器以及TB6612 ...
 - [TcaplusDB知识库]数据库支撑底盘引擎计算层介绍
			
在上次的TcaplusDB知识库中,TcaplusDB君为大家讲解了TcaplusDB所用的基于HASH表的Key-value存储引擎TXHDB.存储引擎作为数据库的支撑底盘,其重要性无可置疑,而在本 ...
 - deepin下zerotier组网
			
环境:deepin 1.安装zerotier curl -s https://install.zerotier.com/ | sudo bash 官网也是有的 安装完成之后进行内网连接 sudo ze ...