2017.9.26 树链剖分+线段树 解题报告
来源:互联网 发布:数控铣床编程30例带图 编辑:程序博客网 时间:2024/05/17 21:41
Description
给出一颗树
三种操作
从u到v的简单路径上的所有点的值都增加v。
从u到v的简单路径上的所有点的值都变为v。
询问从u到v的简单路径上的所有点的值的和是否能表示成两个质数相加的和。
【解题报告】
写起来浑身难受,可能是因为没有看黄历吧。
想着很简单,链剖+线段树(区间加,区间赋值,区间求和)+线筛判素数。
写着很恼火。
代码如下:
#pragma GCC optimize(3)#pragma G++ optimize(3)#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define root 1,1,n#define ls rt<<1#define rs rt<<1|1#define lson rt<<1,l,m#define rson rt<<1|1,m+1,r#define N 100010#define M 10000010#define inf 0x3f3f3f3fint n,m;int prime[M],tot;bool vis[M],judge[M];int top[N],dep[N],fa[N],son[N],siz[N];int tid[N],rank[N],num[N],idc=0;int sum[N<<2],laz[N<<2],set[N<<2];int head[N],cnt;struct Edge{int v,nxt;}e[N<<1];namespace Prime{ void pri() { tot=0; memset(vis,0,sizeof(vis)); memset(judge,0,sizeof(judge)); for(int i=2;i<M;++i) { if(!vis[i]) prime[++tot]=i; for(int j=1;j<=tot&&i*prime[j]<M;++j) { vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } for(int i=4;i<M;i+=2) judge[i]=1; for(int i=1;i<=tot;++i) judge[prime[i]+2]=1; }}namespace DFS{ void adde(int u,int v) { e[++cnt].nxt=head[u];e[cnt].v=v;head[u]=cnt; e[++cnt].nxt=head[v];e[cnt].v=u;head[v]=cnt; } void dfs1(int u,int pre,int deep) { dep[u]=deep;fa[u]=pre;siz[u]=1; for(int i=head[u];~i;i=e[i].nxt) { int v=e[i].v; if(v==pre) continue; dfs1(v,u,deep+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } void dfs2(int p,int tp) { top[p]=tp;tid[p]=++idc;rank[tid[p]]=p; if(son[p]==-1) return; dfs2(son[p],tp); for(int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if(v!=fa[p]&&v!=son[p]) dfs2(v,v); } }}namespace Seg{ void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void pushdown(int rt,int len) { if (set[rt]!=-inf) { sum[rt<<1]=set[rt]*(len-(len>>1)); sum[rt<<1|1]=set[rt]*(len>>1); set[rt<<1]=set[rt<<1|1]=set[rt]; laz[rt<<1]=laz[rt<<1|1]=0; set[rt]=-inf; } if (laz[rt]!=-inf) { sum[rt<<1]+=laz[rt]*(len-(len>>1)); sum[rt<<1|1]+=laz[rt]*(len>>1); if (laz[rt<<1]!=-inf) laz[rt<<1]+=laz[rt]; else laz[rt<<1]=laz[rt]; if (laz[rt<<1|1]!=-inf) laz[rt<<1|1]+=laz[rt]; else laz[rt<<1|1]=laz[rt]; laz[rt]=-inf; } } void build(int rt,int l,int r) { set[rt]=-inf,laz[rt]=-inf; if (l==r) {sum[rt]=num[rank[l]];return ;} int m=(l+r)>>1; build(lson),build(rson); pushup(rt); } void update1(int rt,int l,int r,int L,int R,int val) { if (L<=l&&r<=R) { sum[rt]+=val*(r-l+1); if (laz[rt]==-inf) laz[rt]=val; else laz[rt]+=val; return ; } pushdown(rt,r-l+1); int m=(l+r)>>1; if (L<=m) update1(lson,L,R,val); if (m<R) update1(rson,L,R,val); pushup(rt); } void update2(int rt,int l,int r,int L,int R,int val) { if (L<=l&&r<=R) { sum[rt]=val*(r-l+1); laz[rt]=-inf,set[rt]=val; return ; } pushdown(rt,r-l+1); int m=(l+r)>>1; if (L<=m) update2(lson,L,R,val); if (m<R) update2(rson,L,R,val); pushup(rt); } int query(int rt,int l,int r,int L,int R) { if (L<=l&&r<=R) return sum[rt]; pushdown(rt,r-l+1); int m=(l+r)>>1,res=0; if (L<=m) res+=query(lson,L,R); if (m<R) res+=query(rson,L,R); return res; } void modify(int x,int y,int val,int type) { while (top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y; if (type==1) update1(root,tid[top[x]],tid[x],val); else update2(root,tid[top[x]],tid[x],val); x=fa[top[x]]; } if (dep[x]<dep[y]) x^=y^=x^=y; if (type==1) update1(root,tid[y],tid[x],val); else update2(root,tid[y],tid[x],val); }}using namespace Prime;using namespace DFS;using namespace Seg;int final_judge(int x,int y) { int res=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); res+=query(root,tid[top[x]],tid[x]); x=fa[top[x]]; } if (dep[x]<dep[y]) x^=y^=x^=y; res+=query(root,tid[y],tid[x]); return res;}int main() { freopen("japari.in","r",stdin); freopen("japari.out","w",stdout); pri();cnt=-1; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) { scanf("%d",&num[i]); } for(int i=1;i<n;++i) { int u,v;scanf("%d%d",&u,&v); adde(u,v); } dfs1(1,0,0);dfs2(1,1); build(root); for(int i=1;i<=m;++i) { int opt,x,y,v; scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&x,&y,&v); modify(x,y,v,1); } if(opt==2) { scanf("%d%d%d",&x,&y,&v); modify(x,y,v,0); } if(opt==3) { scanf("%d%d",&x,&y); puts(judge[final_judge(x,y)]?"SUGOI":"TANOSHI"); } } return 0;}
阅读全文
0 0
- 2017.9.26 树链剖分+线段树 解题报告
- 线段树_POJ2528_解题报告
- [ZJOI2016]线段树 解题报告
- 2017.9.28 线段树永久标记 解题报告
- HDU 5209 Relief grain 解题报告(树链剖分 + 线段树)
- Binary Simulation 解题报告--线段树
- HDU1166 敌兵布阵 解题报告--线段树
- HDU3074 Multiply game 解题报告--线段树
- 解题报告:线段树查询 II
- 解题报告:线段树的查询
- 解题报告:线段树的修改
- HDU 1166 解题报告 线段树
- 二维线段树解析 (HDU1823)解题报告
- 线段树 POJ2777 Count Color 解题报告
- 【解题报告】hdu1255 线段树+扫描线
- HDU 1166 线段树 解题报告
- HDU 1754 线段树 解题报告
- POJ 3468 线段树 解题报告
- Mesh Filter和Mesh Renderer
- MOF原理和实现
- 字符集、codepages、setlocal
- 李文星疑被饿死,尸检显示胃里“毫无食物”; 小米可穿戴设备全球第一,出货量超苹果30%
- YLBTool.framework YLBKit.framework 使用规范
- 2017.9.26 树链剖分+线段树 解题报告
- Idea中自动提示忽略大小写
- 2.6基本算法之动态规划 7624:山区建小学——区间DP
- 基础算法学习之排序篇(js实现)
- mybatis实现mapper文件热部署
- codevs 1995 黑魔法师之门 并查集 解题报告
- 2017-9-25离线赛总结
- 在服务器上运行Java程序,依赖文件夹中的jar包
- 王思聪的狗可可刷爆朋友圈;易到超40万司机成功提现;董明珠称5年内不讨论接班人...