9.26NOIP模拟 树链剖分

这道题调了那么久居然是最后的judge错了……
没有考虑m=0和m=1的情况

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+5;
int n,m;
int a[N];
int to[2*N],nxt[2*N],head[N],etot;
int dep[N],fat[N],son[N],size[N];
int top[N],in[N],seq[N],idc;
int prime[N],siz;bool isprime[N];
struct node{
    node *ls,*rs;
    int vsum,del,chg;
    void pushdown(int lf,int rg){
        int mid=(lf+rg)>>1;
        if(chg!=-1){
            ls->chg=chg;
            rs->chg=chg;
            ls->del=0;
            rs->del=0;
            ls->vsum=(mid-lf+1)*chg;
            rs->vsum=(rg-mid)*chg;
            chg=-1;
        }
        if(del!=0){
            ls->del+=del;
            rs->del+=del;
            ls->vsum+=(mid-lf+1)*del;//(ls->del);
            rs->vsum+=(rg-mid)*del;//(rs->del);
            //若子节点之前也有del说明之前也更新到过它,那del已经加给它过了
            //这次只用加这次的del即可 
            del=0;
        }
    }
}pool[2*N+5],*tail=pool,*rt;
void adde(int u,int v)
{
    to[++etot]=v;
    nxt[etot]=head[u];
    head[u]=etot;
}
void dfs1(int u,int fa)
{
    dep[u]=dep[fa]+1;
    fat[u]=fa;
    size[u]=1;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==fa) continue;
        dfs1(v,u);
        if(son[u]==-1||size[v]>size[son[u]]) son[u]=v;
        size[u]+=size[v];
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;
    in[u]=++idc;
    seq[idc]=u;
    if(son[u]!=-1) dfs2(son[u],tp);
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==fat[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}
node *build(int lf,int rg)
{
    node *nd=++tail;
    if(lf==rg){
        nd->vsum=a[seq[lf]];
        nd->del=0;
        nd->chg=-1;
        return nd;
    }
    int mid=(lf+rg)>>1;
    nd->ls=build(lf,mid);
    nd->rs=build(mid+1,rg);
    nd->del=0;
    nd->chg=-1;
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
//  nd->update();
    return nd;
}
void modify_del(node *nd,int L,int R,int lf,int rg,int del)
{
    if(L<=lf&&rg<=R){
        //这个点已经没有原来的chg del的干扰了 
        nd->vsum+=del*(rg-lf+1);
        nd->del+=del;
        return;
        //有标记的意义在于表示它的标记还没有向下传递,但是它已经被标记更新了 
    }
    nd->pushdown(lf,rg);
    int mid=(lf+rg)>>1;
    if(L<=mid)  modify_del(nd->ls,L,R,lf,mid,del);
    if(R>mid) modify_del(nd->rs,L,R,mid+1,rg,del);
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
}
void modify_del(int u,int v,int del)
{
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        modify_del(rt,in[top[u]],in[u],1,n,del);
        u=fat[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    modify_del(rt,in[v],in[u],1,n,del);
}
void modify_chg(node *nd,int L,int R,int lf,int rg,int val)
{
    if(L<=lf&&rg<=R){
        nd->del=0;
        nd->chg=val;
        nd->vsum=val*(rg-lf+1);
        return;
    }
    nd->pushdown(lf,rg);
    int mid=(lf+rg)>>1;
    if(L<=mid) modify_chg(nd->ls,L,R,lf,mid,val);
    if(R>mid) modify_chg(nd->rs,L,R,mid+1,rg,val);
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
}
void modify_chg(int u,int v,int val)
{
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        modify_chg(rt,in[top[u]],in[u],1,n,val);
        u=fat[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    modify_chg(rt,in[v],in[u],1,n,val);
}
int query(node *nd,int L,int R,int lf,int rg)
{
    if(L<=lf&&rg<=R)
        return nd->vsum;
    nd->pushdown(lf,rg);
    int mid=(lf+rg)>>1;
    int ans=0;
    if(L<=mid) ans+=query(nd->ls,L,R,lf,mid);
    if(R>mid) ans+=query(nd->rs,L,R,mid+1,rg);
    nd->vsum=nd->ls->vsum+nd->rs->vsum;
    return ans;
}
int query(int u,int v)
{
    int ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans+=query(rt,in[top[u]],in[u],1,n);
        u=fat[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    ans+=query(rt,in[v],in[u],1,n);
    return ans;
}
bool judge(int x)
{
    if(x==2) return 0;
    if(!(x%2)) return 1;
    if(x-2<=100000){
        if(isprime[x-2]) return 1;
        else return 0;
    }
    else {
        for(int i=2;i*i<=x-2;i++)
        if((x-2)%i==0) return 0;
        return 1;   
    }
}
void euler(int primesize)
{
    isprime[1]=0;
    memset(isprime,1,sizeof(isprime));
    for(int i=2;i<=primesize;i++){
        if(isprime[i]) prime[++siz]=i;
        for(int j=1;prime[j]*i<=primesize&&j<=siz;j++){
            isprime[i*prime[j]]=0;
            if(!(i%prime[j])) break;
        }
    }
}
int main()
{
    freopen("japari.in","r",stdin);
    freopen("japari.out","w",stdout);
    euler(100000);
    memset(son,-1,sizeof(son));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        adde(u,v),adde(v,u);
    }
    dfs1(1,1);
    dfs2(1,1);
    rt=build(1,n);
    while(m--){
        int opt,x,y,v;
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d%d%d",&x,&y,&v);
            modify_del(x,y,v);
        }
        if(opt==2){
            scanf("%d%d%d",&x,&y,&v);
            modify_chg(x,y,v);
        }
        if(opt==3){
            scanf("%d%d",&x,&y);
            int m=query(x,y);
            if(judge(m)) printf("SUGOI\n");
            else printf("TANOSHI\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值