noip模拟17
A. 世界线
又是一个看性质决定走向的题目.
打表即可发现就是每个点能到达的点数之和减去已经有的边.
发现直接使用图的遍历算法复杂度并不是很优秀.
于是考虑使用\(bitset\)优化,把每个点的信息传递给所有可以到达\(ta\)的点.
然后我们可以考虑一个垃圾回收算法.
想法来自 Yubai.
可以选择将已经被榨干贡献的点的空间留给别的点.
这个算法很常用,而以后我也使用这个想法在考场上\(A\)掉了题.
不愧是Yubai.
A_code
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define re register ll
#define lf double
#define lb lower_bound
#define mp make_pair
const ll N=6e4+50;
inline void read(ll &ss)
{
ss=0; bool cit=0; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
if(cit) ss=-ss;
}
bitset<N> s[N>>1];
deque<ll> que;
ll m,n,ts,sum,edge,tot;
ll head[N],d[N],ans[N],use[N],with[N];
bool vis[N];
struct I { ll u,v,nxt; } a[N*8];
inline void add(ll u,ll v)
{
a[++ts].u=u;
a[ts].v=v;
a[ts].nxt=head[u];
head[u]=ts;
}
signed main()
{
read(n); read(m);
ll u,v,w;
for(re i=1;i<=m;i++)
{
read(u); read(v);
add(v,u); d[u]++;
}
for(ll i=1;i<=n;i++)
{
if(d[i]==0)
{
que.push_back(i);
use[i]=++edge;
with[edge]=use[i];
}
}
ll now;
while(que.size())
{
ll now=que.front(); que.pop_front();
ans[now]=s[use[now]].count();
//cout<<"now:"<<now<<" skr\n";
s[use[now]].set(now,1);
for(ll i=head[now];i;i=a[i].nxt)
{
if(--d[a[i].v]==0)
{
que.push_back(a[i].v);
}
if(use[a[i].v]==0)
{
if(tot) use[a[i].v]=with[tot--];
else use[a[i].v]=++edge;
// cout<<"a[i].v:"<<a[i].v<<" "<<use[a[i].v]<<" der\n";
}
s[use[a[i].v]]|=s[use[now]];
}
with[++tot]=use[now]; s[use[now]].reset();
}
ll alls=0;
for(re i=1;i<=n;i++)
{
// cout<<ans[i]<<" ";
alls+=ans[i];
}
printf("%d",alls-m);
}
B. 时间机器
一个显然的贪心.我考场上又写挂了..
自此学会要灵活使用\(STL\).
B_code
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define re register ll
#define lf double
#define lb lower_bound
#define mp make_pair
const ll N=5e5+50;
inline void read(ll &ss)
{
ss=0; bool cit=0; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
if(cit) ss=-ss;
}
ll ts,m,n,ans;
ll lsh[N*10];
struct I
{
ll l,r,cnt;
I(){} I(ll a,ll b,ll c){l=a,r=b,cnt=c;}
} a[N],b[N];
bool comp(I i,I j){ return i.l!=j.l ? i.l<j.l : i.r<j.r ; }
multiset<I> s;
bool operator < (const I &i,const I &j) { return i.r<j.r; }
signed main()
{
// freopen("0.in","r",stdin);
// freopen("out","w",stdout);
read(ts);
while(ts--)
{
read(n); read(m);
ll gets=0,sum=0,alls=0,ans=0;
s.clear();
for(re i=1;i<=n;i++)
{
read(a[i].l); read(a[i].r); read(a[i].cnt);
lsh[++alls]=a[i].l; lsh[++alls]=a[i].r;
sum+=a[i].cnt;
}
for(re i=1;i<=m;i++)
{
read(b[i].l); read(b[i].r); read(b[i].cnt);
lsh[++alls]=b[i].l; lsh[++alls]=b[i].r;
}
sort(lsh+1,lsh+1+alls);
alls=unique(lsh+1,lsh+1+alls)-lsh-1;
for(ll i=1;i<=n;i++)
{
a[i].l=lb(lsh+1,lsh+1+alls,a[i].l)-lsh;
a[i].r=lb(lsh+1,lsh+1+alls,a[i].r)-lsh;
}
for(ll i=1;i<=m;i++)
{
b[i].l=lb(lsh+1,lsh+1+alls,b[i].l)-lsh;
b[i].r=lb(lsh+1,lsh+1+alls,b[i].r)-lsh;
}
sort(a+1,a+1+n,comp); sort(b+1,b+1+m,comp);
I temp=(I){0,1e9,0};
s.insert(temp);
multiset<I>::iterator it;
for(re i=1,j=1;i<=n;i++)
{
//it=s.begin();
//while(*it.r<a[i].r) it++;
while(j<=m and b[j].l<=a[i].l)
{
s.insert(b[j]);
j++;
}
while(a[i].cnt && !s.empty())
{
it=s.lower_bound(a[i]);
//cout<<(it->r)<<"\n";
if(it->r==1e9){ans=1; break;}
I tmp=I(it->l,it->r,it->cnt);
s.erase(it);
if(tmp.cnt<=a[i].cnt)
{
a[i].cnt-=tmp.cnt;
tmp.cnt=0;
}
else
{
tmp.cnt-=a[i].cnt;
a[i].cnt=0;
s.insert(tmp);
}
}
if(a[i].cnt) ans=1;
if(ans) break;
}
if(ans==1) printf("No\n");
else printf("Yes\n");
}
return 0;
}
C. weight
题解说的很清楚.
C_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define re register ll
#define lf double
#define mp make_pair
const ll N=(7e4+50)*2;
const ll M=1e5+50;
inline void read(ll &ss)
{
ss=0; bool cit=0; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
if(cit) ss=-ss;
}
ll n,m,sp,ts,cnt;
ll head[N],fa[N],head2[N],dfn[N],top[N],siz[N],rk[N],dep[N],son[N];
ll weight[N],ans[N];
bool inv[M],vis[N];
struct I { ll u,v,w,id,nxt; } a[M*2],b[N*2];
struct II { ll w,l,r,mx,mn,lazy; } tr[N*5];
inline void add(ll u,ll v,ll w)
{
a[++ts].u=u;
a[ts].v=v;
a[ts].w=w;
a[ts].id=ts;
}
inline void add2(ll u,ll v,ll w)
{
b[++ts].u=u;
b[ts].v=v;
b[ts].w=w;
b[ts].nxt=head2[u];
head2[u]=ts;
}
ll find(ll x){ return x==fa[x] ? x : (fa[x]=find(fa[x])) ; }
inline bool comp(I i,I j){ return i.w<j.w; }
void Kruskal()
{
ll u,v,w; ts=0;
for(re i=1;i<=n;i++) fa[i]=i;
sort(a+1,a+1+m,comp);
for(ll i=1;i<=m;i++)
{
u=find(a[i].u); v=find(a[i].v);
if(u==v) continue;
fa[v]=u; inv[i]=1;
add2(a[i].u,a[i].v,a[i].w);
add2(a[i].v,a[i].u,a[i].w);
}
for(re i=1;i<=n;i++)
{
u=find(i);
if(u==fa[1]) vis[i]=1;
}
memset(fa,0,sizeof fa);
return ;
}
void spread(ll x)
{
if(tr[x].lazy!=1e10+50)
{
tr[x<<1].mn=min(tr[x].lazy,tr[x<<1].mn);
tr[x<<1|1].mn=min(tr[x].lazy,tr[x<<1|1].mn);
tr[x<<1].lazy=min(tr[x].lazy,tr[x<<1].lazy);
tr[x<<1|1].lazy=min(tr[x].lazy,tr[x<<1|1].lazy);
tr[x].lazy=1e10+50;
}
return ;
}
void pushup(ll x)
{
tr[x].w=max(tr[x<<1].w,tr[x<<1|1].w);
return ;
}
void dfs1(ll now,ll dad,ll depth)
{
fa[now]=dad; siz[now]=1; dep[now]=depth;
for(re i=head2[now];i;i=b[i].nxt)
{
if(b[i].v==dad) continue;
weight[b[i].v]=b[i].w;
dfs1(b[i].v,now,depth+1);
siz[now]+=siz[b[i].v];
if(siz[b[i].v]>siz[son[now]])
{
son[now]=b[i].v;
}
}
}
void dfs2(ll now,ll high)
{
dfn[now]=++cnt; rk[cnt]=now;
top[now]=high;
if(!son[now]) return ;
dfs2(son[now],high);
for(re i=head2[now];i;i=b[i].nxt)
{
if(b[i].v==son[now] or b[i].v==fa[now]) continue;
dfs2(b[i].v,b[i].v);
}
return ;
}
void build(ll x,ll l,ll r)
{
tr[x].l=l; tr[x].r=r; tr[x].lazy=1e10+50;
if(tr[x].l==tr[x].r)
{
tr[x].w=weight[rk[l]];
tr[x].mn=1e10+50;
return ;
}
ll mid=(l+r)>>1;
build(x<<1,l,mid); build(x<<1|1,mid+1,r);
pushup(x);
}
void update(ll x,ll ql,ll qr,ll val)
{
if(tr[x].l>=ql and tr[x].r<=qr)
{
tr[x].mn=min(tr[x].mn,val);
tr[x].lazy=min(tr[x].lazy,val);
return ;
}
spread(x);
ll mid=(tr[x].l+tr[x].r)>>1;
if(ql<=mid) update(x<<1,ql,qr,val);
if(qr>=mid+1) update(x<<1|1,ql,qr,val);
pushup(x);
return ;
}
ll query_max(ll x,ll ql,ll qr)
{
if(ql>qr) return 0;
if(tr[x].l>=ql and tr[x].r<=qr)
{
return tr[x].w;
}
spread(x);
ll temp=-1;
ll mid=(tr[x].l+tr[x].r)>>1;
if(ql<=mid) temp=max(temp,query_max(x<<1,ql,qr));
if(qr>=mid+1) temp=max(temp,query_max(x<<1|1,ql,qr));
return temp;
}
ll query(ll x,ll pos)
{
if(tr[x].l==tr[x].r) return tr[x].mn;
spread(x);
ll mid=(tr[x].r+tr[x].l)>>1;
if(pos<=mid) return query(x<<1,pos);
else return query(x<<1|1,pos);
}
ll QMAX(ll x,ll y)
{
ll ans=-1;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,query_max(1,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) ans=max(ans,query_max(1,dfn[x]+1,dfn[y]));
return ans;
}
void CHANGE(ll x,ll y,ll val)
{
// cout<<x<<" "<<y<<" "<<val<<'\n';
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(1,dfn[top[x]],dfn[x],val);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) update(1,dfn[x]+1,dfn[y],val);
return ;
}
void Work()
{
for(re i=1;i<=m;i++)
{
if(vis[a[i].u]==0 and vis[a[i].v]==0)
{
ans[a[i].id]=0; continue;
}
if(!inv[i])
{
ans[a[i].id]=QMAX(a[i].u,a[i].v)-1;
CHANGE(a[i].u,a[i].v,a[i].w);
}
}
for(re i=1;i<=m;i++)
{
if(inv[i] and vis[a[i].u] and vis[a[i].v])
{
ans[a[i].id]=query(1,max(dfn[a[i].v],dfn[a[i].u]))-1;
}
}
return ;
}
signed main()
{
// freopen("0.in","r",stdin);
// freopen("out","w",stdout);
read(n); read(m); read(sp);
ll u,v,w;
for(re i=1;i<=m;i++)
{
read(u); read(v); read(w);
add(u,v,w);
}
Kruskal();
dfs1(1,0,1); dfs2(1,1);
build(1,1,cnt);
Work();
for(re i=1;i<=m;i++)
{
if(ans[i]==1e10+49) ans[i]=-1;
printf("%lld ",ans[i]);
}
return 0;
}