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 0x3f3f3f3f
int 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;
}