\(\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的更多相关文章

  1. NOIP模拟17.9.21

    NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...

  2. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  3. NOIP模拟 17.8.20

    NOIP模拟17.8.20 A.阶乘[题目描述]亲爱的xyx同学正在研究数学与阶乘的关系,但是他喜欢颓废,于是他就制作了一个和阶乘有关系的数学游戏:给出两个整数 n,m,令 t = !n,每轮游戏的流 ...

  4. NOIP模拟 17.8.18

    NOIP模拟17.8.18 A.小菜一碟的背包[题目描述]Blice和阿强巴是好朋友但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习阿强巴有 n头奶牛,每头奶牛每天可以产一定量的奶,同时也 ...

  5. NOIP模拟 17.8.15

    NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  6. NOIP模拟 17.8.17

    NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...

  7. NOIP模拟 17.8.16

    NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  8. NOIP模拟 17.8.14

    NOIP模拟17.8.14 (天宇哥哥考察细心程度的题) [样例解释]如果删去第一个 1:在[3,1,2]中有 3 个不同的数如果删去 3:在[1,1,2]中有 2 个不同的数如果删去第二个 1:在[ ...

  9. NOIP模拟 17.9.28

    公交车[问题描述]市内有

  10. Noip模拟17 2021.7.16

    我愿称这场考试为STL专练 T1 世界线 巧妙使用$bitset$当作vis数组使用,内存不会炸,操作还方便,的确是极好的. 但是这个题如果不开一半的$bitset$是会炸内存的,因为他能开得很大,但 ...

随机推荐

  1. homeless靶机

    仅供个人娱乐 靶机信息 下载地址:https://www.vulnhub.com/entry/homeless-1,215/ 一.主机扫描 二.信息收集 在网页源码和页面上,我们发现User-Agen ...

  2. Lambda--Optional、Collectors高级进阶方法

    Lambda--Collectors.optional高级使用 偶然看到了同事groupingBy用法,然后百度衍生出了optional,collectors,map等各种用法.突然发现自己之前写的代 ...

  3. Java8 Lambda表达式(一)

    目录 一.应用场景引入 优化一:使用策略模式 优化二:使用匿名内部类 优化三:使用Lambda表达式 优化四:使用Stream API 二.Lambda运算符和对应语法 语法格式 Lambda表达式需 ...

  4. Linux命令(五)之service服务查找、启动/停止等相关操作

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  5. Promise教程及用法

    目录 1,介绍 2,特点 3,缺点 4,基本用法 5,then 6,catch 7,finally 8,all() 9,race() 10,allSettled() 11,any() 12,现有对象转 ...

  6. Deepin Pwn环境的配置

    要学习Pwn  Pwn环境那是必不可少滴! 我是新手,我也弄了好久,这里把经验分享给大家!这里感谢I春秋的"知世"老师的脚本!虽然写的不是很完美.还得我自己动手修改!PS:http ...

  7. Setup a Simple HTTP Proxy Server

    The host 10.21.3.69 has no H3C client, so it can't access the internet. With Tinyproxy, we can setuu ...

  8. Create Shortcut for SSH Hosts

    You frequently visit host 10.0.7.141 for example. It's a waste to type "ssh gcp@10.0.7.141" ...

  9. ESP32-S2原生USB 烧录 TinyUF2 bootloader 加 CircuitPython

    概述 ESP32-S2最令我心仪的改进是原生支持USB,即带有一个集成了收发器的全速 USB OTG 外设,符合 USB 1.1 规范,理论速度1.5m/s,利用得当将会是一个非常巨大的进步. 目前E ...

  10. Avro使用手册

    1. Overview Data serialization is a technique of converting data into binary or text format. There a ...