[hackerrank w25]DAG Queries 解题报告
来源:互联网 发布:爱淘宝怎么卸载 编辑:程序博客网 时间:2024/05/18 03:16
题意:
给出一个n个点,m条边的dag,每个点有点权
1 u x:将所有u能到达的点的权值设为x。
2 u x:将所有u能到达的点的权值对x取min。
3 u:查询u的点权。
又用bitset强上了一道题好开心啊~(然而这题标算似乎就是bitset?)
如果暴力的话,可以用bitset,但是空间爆炸;所以我们先解决一下空间问题。
如果考虑对操作分块的话,我们可以只用处理所有节点能否由块内的操作节点抵达,这样首先就可以解决bitset的空间问题!
然后一开始我是这样想的:
如果我们可以
但是我们仔细考虑一下,对u的询问的答案是能到达它的最后一个1操作的x和之间所有的2操作的x最小值。这样的话其实我们没必要处理出每个块的最终状态。我们只需要找到这最后一个1在哪个块里,这是可以对每个块用一个
时间复杂度
看了题解,发现它是这么解决空间问题的:把所有的节点分成3份,对于暴力部分计算3次——这时我才突然明白,bitset可以开到
发现不知不觉似乎已经用这种类似对时间分块的方法a了很多题了。。而且做法主要是有两种,一种是处理出每个块的最终状态,这种适用于那种很多操作一起处理比较方便的,一种是查询的是一个点,那么我们可以分块找出这个点。
似乎如果允许离线,而且本来的点与点之间的关系比较奇怪,对时间分块还是一个不错的搞法呢~
代码:
#include<stdio.h>#include<iostream>using namespace std;#include<algorithm>#include<cstring>#include<bitset>char * cp=(char *)malloc(4000000);inline void in(int &x){ while(*cp<'0'||*cp>'9')++cp; for(x=0;*cp>='0'&&*cp<='9';)x=x*10+(*cp++^'0');}const int N=1e5+5,M=1e5+5,Q=1e5+5;int nxt[M],succ[M],ptr[N],etot=1;inline void addedge(int u,int v){ nxt[etot]=ptr[u],ptr[u]=etot,succ[etot++]=v;}bool exist_deg[N];int indeg[N];int topo[N],ttot=1;void topo_dfs(int node){ topo[ttot++]=node; for(int i=ptr[node];i;i=nxt[i]) if(--indeg[succ[i]]==0) topo_dfs(succ[i]);}struct PS{ int opt,u,x,i;}perform[Q];struct QS{ int u,i;}que[Q];int ans[Q];const int B=316;//const int B=4;bitset<320> b[N];bool cover[N];int Min[N];int main(){ freopen("dagq.in","r",stdin); freopen("dagq.out","w",stdout); fread(cp,1,4000000,stdin); int n,m,q; in(n),in(m),in(q); for(int u,v;m--;) { in(u),in(v); addedge(u,v); exist_deg[v]=1; ++indeg[v]; } for(int i=n;i;--i) if(!exist_deg[i]) topo_dfs(i); int ptot=0,qtot=0; for(int i=1;i<=q;++i) { in(perform[ptot].opt); if(perform[ptot].opt<=2) { in(perform[ptot].u),in(perform[ptot].x); perform[ptot++].i=i; } else { in(que[qtot].u); que[qtot++].i=i; } } memset(ans,127,sizeof(ans)); //printf("ptot=%d,qtot=%d\n",ptot,qtot); for(int l=(ptot-1)-(ptot-1)%B,r=ptot-1;l>=0;r=l-1,l-=B) { /*printf("---[%d,%d]:[%d,%d]---\n",l,r,perform[l].i,perform[r].i); printf("perform="); for(int i=l;i<=r;++i)printf("(opt=%d,u=%d,x=%d,i=%d) ",perform[i].opt,perform[i].u,perform[i].x,perform[i].i); puts("");*/ for(int i=n;i;--i)b[i].reset(); for(int i=l;i<=r;++i)b[perform[i].u][i-l]=1; for(int i=1;i<=n;++i) for(int j=ptr[topo[i]];j;j=nxt[j]) b[succ[j]]|=b[topo[i]]; /*for(int i=1;i<=n;++i) { printf("%d:",topo[i]); for(int j=0;j<=r-l;++j)printf("%d",(int)b[topo[i]][j]); puts(""); }*/ memset(cover,0,sizeof(cover)); for(int i=l;i<=r;++i) if(perform[i].opt==1) cover[perform[i].u]=1; for(int i=1;i<=n;++i) if(cover[topo[i]]) for(int j=ptr[topo[i]];j;j=nxt[j]) cover[succ[j]]=1; memset(Min,127,sizeof(Min)); for(int i=l;i<=r;++i) if(perform[i].opt==2) Min[perform[i].u]=min(Min[perform[i].u],perform[i].x); for(int i=1;i<=n;++i) for(int j=ptr[topo[i]];j;j=nxt[j]) Min[succ[j]]=min(Min[succ[j]],Min[topo[i]]); { int i=qtot; while(i&&que[i-1].i>perform[l].i)--i; while(i<qtot) { //printf("Q:u=%d,i=%d,now=%d\n",que[i].u,que[i].i,ans[que[i].i]); if(que[i].i<perform[r].i) { int j=r; while(perform[j].i>que[i].i)--j; for(;j>=l;--j) if(b[que[i].u][j-l]) { ans[que[i].i]=min(ans[que[i].i],perform[j].x); if(perform[j].opt==1) { swap(que[i],que[--qtot]); break; } } i+=j<l; } else if(cover[que[i].u]) { int j=r; for(;perform[j].opt==2||!b[que[i].u][j-l];--j) if(perform[j].opt==2&&b[que[i].u][j-l]) ans[que[i].i]=min(ans[que[i].i],perform[j].x); ans[que[i].i]=min(ans[que[i].i],perform[j].x); swap(que[i],que[--qtot]); } else { ans[que[i].i]=min(ans[que[i].i],Min[que[i].u]); ++i; } } } } while(qtot--)ans[que[qtot].i]=0; for(int i=1;i<=q;++i) if(ans[i]<=1e9) printf("%d\n",ans[i]);}
总结:
①一定要想好细节再写代码!
②bitset占的内存是
③对时间分块:对每个块处理出最终状态;操作对查询的影响是一个关于时间的点/区间。
- [hackerrank w25]DAG Queries 解题报告
- [HackerRank Week of Code]DAG Queries/[JZOJ5038]命运的构造
- POJ1986 Distance Queries LCA pascal 解题报告
- POJ-1986-Distance Queries 解题报告
- 【POJ 1986】 Distance Queries 解题报告
- [hackerrank]Range Modular Queries
- POJ1949 Chores 解题报告【拓扑排序/DAG最长路】
- BZOJ 1093 [ZJOI 2007] Tarjan+DAG拓扑排序DP 解题报告
- HDU 1151 二分图的DAG最小路径覆盖 解题报告
- [Hackerrank Week of Code 30]Range Modular Queries
- Hackerrank Week of Code 30 Range Modular Queries
- [后缀自动机][分块]HackerRank Week of Code 30 .Substring Queries
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 第七周项目3-负数把正数赶出队列
- POJ 3616 Milking time
- cmd命令行 查找文件的方式丨Windows
- POJ Problem 2406 Power Strings
- 404. Sum of Left Leaves
- [hackerrank w25]DAG Queries 解题报告
- 第七周项目4-队列数组
- 51nod 1051【基础】
- 深度学习资料一
- libGDX开发环境搭建-Android Studio 最新版
- 欢迎使用CSDN-markdown编辑器
- Leetcode||16.3Sum Closest
- 修改checkbox样式
- 【hdu 2594】Simpsons’ Hidden Talents(kmp)