T1
考场上有一部分答案算重了,没有判掉,然后就死了,正解是$bitset$乱搞
记录一下每个点能够到达哪些点,然后减去他的直系儿子,就是最后对答案造成的贡献,每个点能够达到的点由他儿子传过来即可,为了避免多次无用搜索,我们从入度为0的点开始搜,这样的话可以尽量的减少重复搜索的点,但同时由于他是有向边,你还是会有点跑两遍,所以判一下,如果已经跑过了没,就不跑了,直接传信息
但是我们会发现,我们就算用$bitset$,依旧会炸空间,考虑优化,他们是按拓扑序分层转移,而我不会,所以我搜了一半,分两次搜,一次只有前一半的点做贡献,一次只有后一半的点做贡献,把答案加起来,多余的贡献就是$n+m$,减掉就好了
1 #include2 #include 3 #include 4 #include 5 #include 6 #define maxx 61000 7 #define maxn 31000 8 #define maxm 100100 9 using namespace std; 10 int n,m,u,v,js,ans,mid,opt; 11 int head[maxx],to[maxm],xia[maxm],pd[maxx],du[maxx]; 12 bitset a[maxx]; 13 vector <int> sou; 14 void add(int x,int y) 15 { 16 to[++js]=y; xia[js]=head[x]; head[x]=js; du[y]++; 17 } 18 void dfs(int x) 19 { 20 pd[x]=1; 21 if(!opt&&x<=mid) a[x][x]=1; 22 if(opt&&x>mid) a[x][x-mid]=1; 23 for(int i=head[x];i;i=xia[i]) 24 { 25 int ls=to[i]; 26 if(!pd[ls]) dfs(ls); 27 a[x]|=a[ls]; 28 } 29 } 30 int main() 31 { 32 // freopen("worldline2.in","r",stdin); 33 scanf("%d%d",&n,&m); 34 for(int i=1;i<=m;++i) {scanf("%d%d",&u,&v); add(u,v);} 35 for(int i=1;i<=n;++i) 36 if(!du[i]) sou.push_back(i); 37 mid=n/2; 38 for(int i=0;i i) dfs(sou[i]); 39 for(int i=1;i<=n;++i) {ans+=a[i].count(); a[i].reset();} 40 memset(pd,0,sizeof(pd)); opt=1; 41 for(int i=0;i i) dfs(sou[i]); 42 for(int i=1;i<=n;++i) {ans+=a[i].count(); a[i].reset();} 43 printf("%d\n",ans-m-n); 44 return 0; 45 }
T2
考场上想到了贪心,但是由于$STL$玩的不够溜,没敢用$set$,手动找的转移点,然后就找死了
我想的贪心是找范围最靠近这个节点的电阻,放给他,这样我就会有左端点,右端点两种限制,考虑怎么可以去掉一个,等等,先离散化一下再继续,因为我们需要用范围当下标,离散化之后,把电阻和节点信息全部按左端点从小到大排序,然后扫每一个节点,如果当前有左节点符合条件的电阻,就把右端点扔进$set$里,这样的话$set$里是所有可用电阻,左端点就不会造成限制了,我们就成功去掉了一个限制,在保证左端点合法的$set$中,$lower$_$bound$出最靠左的右端点合法的位置,放满这个节点,或没有可以放在这个节点的电阻之后进入下一个节点即可,由于$set$自动去重,所以需要开个桶看右端点在这个位置的电阻有多少个,或许$multiset$也可以吧
1 #include2 #include 3 #include 4 #include 5 #include<set> 6 #define maxn 50100 7 using namespace std; 8 struct node{ 9 int l,r,num; 10 }nn[maxn],mm[maxn]; 11 int lsh[maxn*8],tong[maxn*8]; 12 int T,n,m,bj,head,tot,len; 13 set <int> s; 14 inline int read() 15 { 16 int e=0; char ch=getchar(); 17 while(ch<'0'||ch>'9') ch=getchar(); 18 while(ch>='0'&&ch<='9') {e=(e<<3)+(e<<1)+(ch^48); ch=getchar();} 19 return e; 20 } 21 bool cmp(const node &a,const node &b) 22 { 23 return a.l<b.l; 24 } 25 void clear() 26 { 27 bj=0; head=1; tot=0; s.clear(); 28 memset(nn,0,sizeof(nn)); memset(mm,0,sizeof(mm)); 29 memset(lsh,0,sizeof(lsh)); memset(tong,0,sizeof(tong)); 30 } 31 int main() 32 { 33 T=read(); 34 while(T--) 35 { 36 n=read(); m=read(); clear(); 37 for(int i=1;i<=n;++i) 38 { 39 nn[i].l=read(); nn[i].r=read(); nn[i].num=read(); 40 lsh[++tot]=nn[i].l; lsh[++tot]=nn[i].r; 41 } 42 for(int i=1;i<=m;++i) 43 { 44 mm[i].l=read(); mm[i].r=read(); mm[i].num=read(); 45 lsh[++tot]=mm[i].l; lsh[++tot]=mm[i].r; 46 } 47 sort(lsh+1,lsh+tot+1); 48 len=unique(lsh+1,lsh+tot+1)-lsh-1; 49 for(int i=1;i<=n;++i) 50 { 51 nn[i].l=lower_bound(lsh+1,lsh+len+1,nn[i].l)-lsh; 52 nn[i].r=lower_bound(lsh+1,lsh+len+1,nn[i].r)-lsh; 53 } 54 for(int i=1;i<=m;++i) 55 { 56 mm[i].l=lower_bound(lsh+1,lsh+len+1,mm[i].l)-lsh; 57 mm[i].r=lower_bound(lsh+1,lsh+len+1,mm[i].r)-lsh; 58 } 59 sort(nn+1,nn+n+1,cmp); sort(mm+1,mm+m+1,cmp); 60 for(int i=1;i<=n;++i) 61 { 62 while(mm[head].l<=nn[i].l&&head<=m) 63 { 64 s.insert(mm[head].r); tong[mm[head].r]+=mm[head].num; head++; 65 } 66 while(1) 67 { 68 if(nn[i].num==0) break; 69 set<int>::iterator it=s.lower_bound(nn[i].r); 70 if(it==s.end()) break; 71 int ji=min(nn[i].num,tong[*it]); 72 nn[i].num-=ji; tong[*it]-=ji; 73 if(!tong[*it]) s.erase(it); 74 } 75 } 76 for(int i=1;i<=n;++i) 77 if(nn[i].num) {bj=1; break;} 78 if(bj) printf("No\n"); 79 else printf("Yes\n"); 80 } 81 return 0; 82 }
T3
不会做,咕咕咕人类的本质就是咕咕咕