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;}
原创粉丝点击