5.4
考中:
t1看了一眼,感觉像淀粉质,思考了一下,发现可以,而且代码难度也不高,在继续看和写代码之间选择了写代码,然后,果不其然,我又双叒叕想了个假算法,心塞,看了看暴力,只会30分,开始写30分的,写完以后,又思考了一下原来的错误做法,发现其实没错,又看了一眼题面,然后,果不其然,我又双叒叕看错题了,呵呵,于是看t2,很好,有30分,然后看t3,有60分,算了算,有110分,感觉还行,代码都还好,于是找看了一圈,发现没有老师,找zyz商量了一下,于是回寝室了
t1:
10分,直接枚举
30分,直接dfs一下,上组合数
剩下的待填
t2:
60分:直接做(应该没有人不会吧,我就不会)
截止时间 i 的答案ans 应当是满足 j*k >= 截止时间在 k 及以前的订单数量 k=1,2,……i 的最小的 j
100分:待填
t3:
50分:bitset搞一下就完了
100分:
考虑50分的瓶颈,在于无法直接根据某些东西快速求出后面的点集,考虑拓扑的过程。
所以我们考虑dfs序,显然是后序,容易发现:所以x可以走到的点其实是dfs后序在x前面的点,但这样我们会发现有不合法的点,不合法的点是dfs v 结束后,dfs 接下来的v得到的,所以翻转一下从x连出去的点,dfs后序同时<=x的点就可以刚好被加入答案了
给的题解实际上更复杂了
代码:
#include<bits/stdc++.h> using namespace std; const int N=300005,M=400000+5; struct er{ int x,y,v; }dian[N]; struct qw{ int x,v; }; int cmp(qw l,qw r) { return l.v<r.v; } vector<qw> next1[N]; int ru_1[N],ru_2[N]; void lian(int x,int y,int v) { next1[x].push_back((qw){y,v}); ru_1[y]++; ru_2[y]++; } int dfn1[N],dfn2[N],tim; int rnk[N]; void dfs_1(int x) { tim++; rnk[tim]=x; for(int i=0;i<next1[x].size();i++) { int v=next1[x][i].x; ru_1[v]--; if(!ru_1[v]) dfs_1(v); } } void dfs_2(int x) { tim++; rnk[tim]=x; for(int i=0;i<next1[x].size();i++) { int v=next1[x][i].x; ru_2[v]--; if(!ru_2[v]) dfs_2(v); } } int c[N],n; void add(int x,int v) { if(x==0) return; while(x<=n) { c[x]+=v; x+=x&-x; } } int query(int x) { int res=0; while(x) { res+=c[x]; x-=x&-x; } return res; } int ans[N],f[N]; int main() { freopen("souvenir.in","r",stdin); freopen("souvenir.out","w",stdout); int m; cin>>n>>m; int x,y; for(int i=1;i<=n;i++) scanf("%d %d %d",&dian[i].x,&dian[i].y,&dian[i].v); while(m--) { scanf("%d %d",&x,&y); if(dian[y].x>dian[x].x||dian[y].y>dian[x].y) lian(x,y,dian[y].x>dian[x].x); else lian(y,x,dian[x].x>dian[y].x); } // for(int i=1;i<=n;i++) sort(next1[i].begin(),next1[i].end(),cmp); dfs_1(1); for(int i=1;i<=n;i++) dfn1[rnk[i]]=n-i+1; tim=0; for(int i=1;i<=n;i++) reverse(next1[i].begin(),next1[i].end()); dfs_2(1); for(int i=1;i<=n;i++) dfn2[rnk[i]]=n-i+1;//图的拓扑序,不能直接dfs后面加tim++,应该等x的y全部遍历完才能把x丢进去 for(int i=n;i>=1;i--) { x=rnk[i]; add(f[dian[x].v],-1); if(!f[dian[x].v]) f[dian[x].v]=dfn1[x]; else f[dian[x].v]=min(f[dian[x].v],dfn1[x]); add(f[dian[x].v],1); ans[x]=query(dfn1[x]);//不能这里-1,ans+1,因为query统计的是颜色,而-1以后有的点会统计到自己的颜色,有的点不会 } for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; } /* 7 7 1 1 1 3 1 2 1 2 1 2 2 3 3 3 4 2 4 1 3 4 2 1 2 1 3 4 3 5 2 5 7 4 6 7 6 */