csp-s模拟测试42「世界线·时间机器·密码」
$t3$不会
世界线
题解
题目让求的就是每个点能到点的数量$-$出度
设每个点能到的点为$f[x]$
则$f[x]=x \sum\limits_{y}^{y\in son[x]} U f[y]$
用$bitset$优化一下即可,但单纯这样会炸内存,随意$yy$一下,时间换空间,像平衡树一样开个垃圾桶都行
代码
#include<bits/stdc++.h> using namespace std; #define ll int #define A 60001 ll dl[A],ans[A],head[A*5],nxt[A*5],ver[A*5],out[A],in[A]; ll n,m,tot,sbzzn=0; bitset<5005> bit[A]; void add(ll x,ll y){ nxt[++tot]=head[x],head[x]=tot,ver[tot]=y; } void top(){ deque<ll> q; for(ll i=1;i<=n;i++) if(in[i]==0) q.push_back(i); while(!q.empty()){ ll top_now=q.front(); // printf("dl[0]=%d top_now=%d\n",dl[0],top_now); dl[++dl[0]]=top_now; q.pop_front(); for(ll i=head[top_now];i;i=nxt[i]){ ll y=ver[i]; // printf("top_now=%d y=%d in[y]=%d\n",top_now,y,in[y]); in[y]--; if(in[y]==0) q.push_back(y); } } } void count(){ for(ll l=1,r=5000;l<=n;l=r+1,r+=5000){ for(ll i=1;i<=n;i++) bit[i].reset(); for(ll i=dl[0];i>=1;i--){ ll x=dl[i]; for(ll j=head[x];j;j=nxt[j]){ ll y=ver[j]; bit[x]|=bit[y]; } ans[x]+=bit[x].count(); if(x>=l&&x<=r) bit[x][x-l]=1; } } for(ll i=1;i<=n;i++){ sbzzn+=ans[i]-out[i]; } printf("%d\n",sbzzn); } int main(){ //freopen("worldline2.in","r",stdin); //freopen("haha2.in","w",stdout); scanf("%d%d",&n,&m); for(ll i=1,a,b;i<=m;i++){ scanf("%d%d",&a,&b); in[b]++; out[a]++; add(a,b); } top(); count(); }
时间机器
题解
贪心,简单线段覆盖贪心,按照左端点排序,从左端点找到右端点最靠左且能覆盖的解
验证正确性
每次枚举到左端点之前所有比当前左端点还靠左的端点都已经考虑完,若当前取不是最符合的一定不会使结果变优,若当前点放不了一定无解
代码
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 501010 ll T; ll n,m; struct node{ ll l,r,cnt,op; friend bool operator < (const node &a,const node &b){ return (a.l==b.l)?a.op<b.op:a.l<b.l; } }t[A]; map<ll,ll> mp; map<ll,ll> :: iterator it; ll read(){ ll f=1,x=0;char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); } return f*x; } int main(){ T=read(); while(T--){ n=read();m=read(); mp.clear(); ll cnt=0;//先节点,再电阻 for(ll i=1;i<=n;i++) t[++cnt].l=read(),t[cnt].r=read(),t[cnt].cnt=read(),t[cnt].op=1; for(ll i=1;i<=m;i++) t[++cnt].l=read(),t[cnt].r=read(),t[cnt].cnt=read(),t[cnt].op=-1; ll ok=1;//printf("oo\n"); sort(t+1,t+1+cnt); //存节点,拿节点匹配电阻 for(ll i=1;i<=cnt;i++){ //printf("t.op=%lld\n",t[i].op); if(t[i].op==-1) mp[t[i].r]+=t[i].cnt; else{ while(t[i].cnt){ it=mp.lower_bound(t[i].r); // printf("mp[%lld]=%lld\n",t[i].r,mp[t[i].r]); if(it==mp.end()){ ok=0; break; } if(t[i].cnt>=it->second) t[i].cnt-=it->second,mp.erase(it); else it->second-=t[i].cnt,t[i].cnt=0; // printf("mp[%lld]=%lld\n",t[i].r,mp[t[i].r]); } if(!ok)break; } } if(ok==0) printf("No\n"); else printf("Yes\n"); } }
我已没有下降的余地