萌新求助
查看原帖
萌新求助
124918
LinkyChristian楼主2021/10/16 11:03
#include<bits/stdc++.h>
using namespace std;
const long long MAXN=50010;
typedef long long ll;
struct edge{
    long long next,to;
}e[MAXN*2];
struct linetree{
    long long l,r,sum,lazy;
}tree[MAXN*4];
ll N,M,R,P,value[MAXN],eN;
long long head[MAXN],fa[MAXN],d[MAXN],son[MAXN],size[MAXN];
long long cnt,top[MAXN],id[MAXN],rk[MAXN],otpt[MAXN];
struct node{
	long long l,r,z,id;
}qyl[50010],qyr[50010]; 
void insert(long long a1,long long a2) {
    eN++;
    e[eN].next=head[a1];
    e[eN].to=a2;
    head[a1]=eN;
} 

void dfs1(long long now,long long deep,long long f) {
    fa[now]=f;
    d[now]=deep;
    size[now]=1;
    for(long long i=head[now];i;i=e[i].next) {
        long long to=e[i].to;
        if(to!=fa[now]) {
            dfs1(to,deep+1,now);
            size[now]+=size[to];
            if(son[now]==0||size[to]>size[son[now]]) son[now]=to;
        }
    }
}
void dfs2(long long now,long long tp) {
    cnt++;
    id[now]=cnt;
    rk[cnt]=now;
    top[now]=tp;
    if(son[now]) dfs2(son[now],tp);
    for(long long i=head[now];i;i=e[i].next) {
        long long to=e[i].to;
        if(to!=fa[now]&&to!=son[now]) dfs2(to,to);
    }
}
void pushdown(long long k) {
    tree[2*k].lazy=(tree[2*k].lazy+tree[k].lazy)%P;
    tree[2*k+1].lazy=(tree[2*k+1].lazy+tree[k].lazy)%P;
    tree[2*k].sum=(tree[2*k].sum+(tree[2*k].r-tree[2*k].l+1)*tree[k].lazy)%P;
    tree[2*k+1].sum=(tree[2*k+1].sum+(tree[2*k+1].r-tree[2*k+1].l+1)*tree[k].lazy)%P;
    tree[k].lazy=0;
}
void build(long long k,long long l,long long r) {
    tree[k].l=l,tree[k].r=r;
    if(l==r) {
        tree[k].sum=value[rk[l]]%P;
        return ;
    }
    long long mid=(l+r)/2;
    build(2*k,l,mid),build(2*k+1,mid+1,r);
    tree[k].sum=(tree[2*k].sum+tree[2*k+1].sum)%P;
}
ll query(long long k,long long l,long long r) {
    if(l<=tree[k].l&&tree[k].r<=r) return tree[k].sum%P;
    if(tree[k].lazy) pushdown(k);
    long long mid=(tree[k].l+tree[k].r)/2;
    if(r<=mid) return query(2*k,l,r)%P;
    if(l>mid) return query(2*k+1,l,r)%P;
    return (query(2*k,l,r)+query(2*k+1,l,r))%P;
}
void add(long long k,long long l,long long r,long long z)  {
    if(l<=tree[k].l&&tree[k].r<=r) {
        tree[k].sum=(tree[k].sum+(tree[k].r-tree[k].l+1)*z)%P;
        tree[k].lazy=(tree[k].lazy+z)%P;
        return ;
    }
    if(tree[k].lazy) pushdown(k);
    long long mid=(tree[k].l+tree[k].r)/2;
    if(l<=mid) add(2*k,l,r,z);
    if(r>mid) add(2*k+1,l,r,z);
    tree[k].sum=(tree[2*k].sum+tree[2*k+1].sum)%P;
} 
ll sum(long long x,long long y) {
    ll s=0;
    long long topx=top[x],topy=top[y];
    while(topx!=topy) {
        if(d[topx]>=d[topy]) {
            s+=query(1,id[topx],id[x])%P;
            x=fa[topx],topx=top[x]; 
        }
        else {
            s+=query(1,id[topy],id[y])%P;
            y=fa[topy],topy=top[y];
        }
    }
    if(d[x]>=d[y]) s+=query(1,id[y],id[x])%P;
    else s+=query(1,id[x],id[y])%P;
    return s;
}
void noice(long long x,long long y,long long z) {
    long long topx=top[x],topy=top[y];
    while(topx!=topy) {
        if(d[topx]>=d[topy]) {
            add(1,id[topx],id[x],z);
            x=fa[topx],topx=top[x]; 
        }
        else {
            add(1,id[topy],id[y],z);
            y=fa[topy],topy=top[y];
        }
    }
    if(d[x]>=d[y]) add(1,id[y],id[x],z);
    else add(1,id[x],id[y],z);
}
long long cmp1(node a1,node a2) {return a1.l<a2.l;}
long long cmp2(node a1,node a2) {return a1.r<a2.r;}
int main()
{
	freopen("ac.txt","w",stdout);
    cin>>N>>M;
    R=1,P=201314;
    for(long long i=2; i<=N; i++) {
        long long a1;
        cin>>a1;
        a1++;
        insert(a1,i);
        insert(i,a1);
    }
    dfs1(R,1,R);
    dfs2(R,R);
    cnt=0;
    build(1,1,N);
    for(long long i=1; i<=M; i++) {
    	cin>>qyl[i].l>>qyl[i].r>>qyl[i].z;
    	qyl[i].l++,qyl[i].r++,qyl[i].z++,qyl[i].id=i;
    	qyr[i]=qyl[i];
	}
	sort(qyl+1,qyl+M+1,cmp1);
	sort(qyr+1,qyr+M+1,cmp2);
	long long ll=1,rr=1; 
	for(long long i=1; i<=N; i++) {
		noice(1,i,1);
		while(qyl[ll].l-1==i) otpt[qyl[ll].id]=
		    (otpt[qyl[ll].id]+P-sum(1,qyl[ll].z)%P)%P,ll++;
		while(qyr[rr].r==i) otpt[qyr[rr].id]=
		    (otpt[qyr[rr].id]+sum(1,qyr[rr].z)%P)%P,rr++; 
	}
	for(long long i=1; i<=M; i++) cout<<otpt[i]<<endl;
    return 0;
}

样例过了,爆0

前面的树剖是搬运的我自己写的100pt树剖模板,理论上来说不会出错

为了适配使用1~n的点下标,在接受父亲节点,输入父亲节点,输入询问三个参数时都已+1

差分查询用双指针,其中qyl是按照询问左端点排序的询问序列,qyr是按照询问右端点排序的询问序列

其中id指的是一个询问所对应的编号,otpt是对应的输出,输出的结果在左端点-1的时候减去当前结果,在右端点的时候加上当前结果

循环1~i时是先加上从1~i的链再查询所有在i的询问

希望好心人帮助谢谢

2021/10/16 11:03
加载中...