NOIP提高组模拟赛22
博客咕了好久,还是更新一下吧。。。。
A. 世界线
搜索,暴力搜索。。。
答案显然是每个点能到达的点的数目之和减去边数
就是,但是直接搜显然会
于是使用的进行优化
然鹅会
发现空间只够开一半的点,所以分两次,每次处理一半。
code
#include<cstdio>
#include<cstring>
#include<bitset>
using namespace std;
const int maxn=60005;
const int mid=30003;
int n,m;
bitset<mid>s[maxn];
struct gr{
bool flag[maxn];
struct edeg{int net,to;}e[100005];
int head[maxn],tot;
void add(int u,int v){
e[++tot].net=head[u];
head[u]=tot;
e[tot].to=v;
}
void dfs(int x,int op){
flag[x]=1;
if(op==1&&x<mid)s[x].set(x);
if(op==2&&x>=mid)s[x].set(x-mid+1);
for(int i=head[x];i;i=e[i].net){
int v=e[i].to;
if(!flag[v])dfs(v,op);
s[x]=s[x]|s[v];
}
}
void DO(){
for(int i=1;i<=n;++i)
if(!flag[i])dfs(i,1);
long long ans=0;
for(int i=1;i<=n;++i)ans+=s[i].count();
for(int i=1;i<=n;++i)s[i]=s[0];
for(int i=1;i<=n;++i)flag[i]=0;
for(int i=1;i<=n;++i)
if(!flag[i])dfs(i,2);
for(int i=1;i<=n;++i)ans+=s[i].count();
printf("%lld\n",ans-n-m);
}
}G;
int main(){
// freopen("worldline1.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){int u,v;scanf("%d%d",&u,&v);G.add(u,v);}
G.DO();
return 0;
}
B. 时间机器
乱搞++
一个贪心:电阻节点按照左端点排序,对于每个节点选择左边界在自己右边且,右边界最靠近自己的
一个优化:
完了。。。。。
code
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=50005;
int read(){
char c;int x=0;c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x;
}
int n,m;
struct node{int l,r,k;}u[maxn],d[maxn];
bool cmp(node x,node y){return x.l<y.l;}
set<pair<int,int> >s;
bool work(){
s.clear();
int pl=1;
for(int i=1;i<=n;++i){
while(pl<=m&&u[pl].l<=d[i].l){
s.insert(make_pair(u[pl].r,pl));++pl;
}
while(d[i].k){
set<pair<int,int> >::iterator it = s.lower_bound(make_pair(d[i].r,0));
if(it==s.end())return false;
pair<int,int>res=*it;
if(u[res.second].k>d[i].k){
u[res.second].k-=d[i].k;
d[i].k=0;
}else{
d[i].k-=u[res.second].k;
u[res.second].k=0;
s.erase(it);
}
}
}
return true;
}
int main(){
int Q;Q=read();
for(int ask=1;ask<=Q;++ask){
n=read();m=read();
for(int i=1;i<=n;++i)d[i].l=read(),d[i].r=read(),d[i].k=read();
for(int i=1;i<=m;++i)u[i].l=read(),u[i].r=read(),u[i].k=read();
sort(d+1,d+n+1,cmp);sort(u+1,u+m+1,cmp);
if(work())printf("Yes\n");
else printf("No\n");
}
return 0;
}
C. weight
首先随便找个最小生成树,然后钦定一个根
然后随便搞随便切
枚举非树边,当它在所有最小生成树上,它的权应该小于它所连接的两个点树上路径经过的最大权
因为这是最小生成树,所以正确性显然
对于树边,它需要小于所有跨过它的非树边
使用树剖维护一下,然后对于的情况,用并茶几即可
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=70005;
const int maxm=100005;
struct lu{int u,v,w,id;bool flag;}l[maxm];
bool cmp(lu x,lu y){return x.w<y.w;}
int n,m,a,ans[maxm];
struct tree{
struct edge{int net,to,val;}e[maxn<<1|1];
int head[maxn],tot=1,id[maxn],tim;
void add(int u,int v,int w){
e[++tot].net=head[u];
head[u]=tot;
e[tot].to=v;
e[tot].val=w;
}
struct node{
int fa,son,size,dep,val,top,id;
}d[maxn];
void dfs1(int x){
d[x].size=1;
for(int i=head[x];i;i=e[i].net){
int v=e[i].to;
if(v==d[x].fa)continue;
d[v].fa=x;d[v].dep=d[x].dep+1;d[v].val=e[i].val;
dfs1(v);
d[x].size+=d[v].size;
d[x].son=d[d[x].son].size>d[v].size?d[x].son:v;
}
}
void dfs2(int x,int top){
d[x].id=++tim;id[tim]=x;d[x].top=top;
if(d[x].son)dfs2(d[x].son,top);
for(int i=head[x];i;i=e[i].net){
int v=e[i].to;
if(v==d[x].fa||v==d[x].son)continue;
dfs2(v,v);
}
}
#define ls t[x<<1]
#define rs t[x<<1|1]
struct note{
int mx,rem;
bool tag;
note(){mx=-1,rem=2147483647;}
}t[maxn<<2|1];
void push_up(int x){t[x].mx=max(ls.mx,rs.mx);}
void built(int x,int l,int r){
if(l==r){
t[x].mx=d[id[l]].val;
return;
}
int mid=(l+r)>>1;
built(x<<1,l,mid);
built(x<<1|1,mid+1,r);
push_up(x);
}
int q_max(int x,int l,int r,int L,int R){
if(L<=l&&r<=R)return t[x].mx;
int mid=(l+r)>>1,ans=-1;
if(L<=mid)ans=max(ans,q_max(x<<1,l,mid,L,R));
if(R>mid)ans=max(ans,q_max(x<<1|1,mid+1,r,L,R));
return ans;
}
void push_down(int x){
ls.rem=min(ls.rem,t[x].rem);
rs.rem=min(rs.rem,t[x].rem);
ls.tag=rs.tag=1;t[x].tag=0;
}
void m_min(int x,int l,int r,int L,int R,int val){
if(L<=l&&r<=R){
t[x].rem=min(t[x].rem,val);
t[x].tag=1;
return;
}
if(t[x].tag)push_down(x);
int mid=(l+r)>>1;
if(L<=mid)m_min(x<<1,l,mid,L,R,val);
if(R>mid)m_min(x<<1|1,mid+1,r,L,R,val);
}
int query_max(int u,int v,int val){
if(!d[u].fa||!d[v].fa)return 0;
int ans=-1;
while(d[u].top!=d[v].top){
if(d[d[u].top].dep<d[d[v].top].dep)swap(u,v);
ans=max(ans,q_max(1,1,n,d[d[u].top].id,d[u].id));
m_min(1,1,n,d[d[u].top].id,d[u].id,val);
u=d[d[u].top].fa;
}
if(u==v)return ans-1;
if(d[u].dep<d[v].dep)swap(u,v);
ans=max(ans,q_max(1,1,n,d[v].id+1,d[u].id));
m_min(1,1,n,d[v].id+1,d[u].id,val);
return ans-1;
}
int q_mi(int x,int l,int r,int pos){
if(l==r)return t[x].rem;
int mid=(l+r)>>1;
if(t[x].tag)push_down(x);
if(pos<=mid)return q_mi(x<<1,l,mid,pos);
else return q_mi(x<<1|1,mid+1,r,pos);
}
int query_min(int u,int v){
if(!d[u].fa||!d[v].fa)return 0;
if(d[u].fa==v)return q_mi(1,1,n,d[u].id)-1;
else return q_mi(1,1,n,d[v].id)-1;
}
}T;
struct SET{
int f[maxn];
void pre(int n){for(int i=1;i<=n;++i)f[i]=i;}
int fa(int x){return f[x]=f[x]==x?x:fa(f[x]);}
void hb(int x,int y){x=fa(x);y=fa(y);f[y]=x;}
bool ask(int x,int y){return fa(x)==fa(y);}
}S;
int main(){
scanf("%d%d%d",&n,&m,&a);
for(int i=1;i<=m;++i)scanf("%d%d%d",&l[i].u,&l[i].v,&l[i].w),l[i].id=i;
sort(l+1,l+m+1,cmp);
int cnt=0;S.pre(n);
for(int i=1;i<=m;++i){
if(S.ask(l[i].u,l[i].v))continue;
S.hb(l[i].u,l[i].v);
T.add(l[i].u,l[i].v,l[i].w);
T.add(l[i].v,l[i].u,l[i].w);
l[i].flag=1;
++cnt;if(cnt==n-1)break;
}
T.d[1].dep=1;T.d[1].fa=1;T.dfs1(1);T.dfs2(1,1);
T.built(1,1,n);
for(int i=1;i<=m;++i){
if(l[i].flag)continue;
ans[l[i].id]=T.query_max(l[i].u,l[i].v,l[i].w);
}
for(int i=1;i<=m;++i){
if(!l[i].flag)continue;
ans[l[i].id]=T.query_min(l[i].u,l[i].v);
}
for(int i=1;i<=m;++i)if(ans[i]>=2147483640)printf("-1 ");else printf("%d ",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】