• equation


    equation

    题目描述

     

    有一棵n 个点的以 1 为根的树, 以及 n 个整数变量xi。树上 i 的父亲是 fi, 每条边(i,fi)有一个权值wi,表示一个方程 xi + xfi = wi,这 n-1个方程构成了一个方程组。

    现在给出q 个操作,有两种类型:

    1 u v s,表示询问加上 xu + xv = s 这个方程后,整个方程组的解的情况。具体来说, 如果方程有唯一解, 输出此时 x1 的值; 如果有无限多个解,输出 inf;如果无解,输出 none. 注意每个询问是独立的。

    2 u w,表示将 wu 修改为 w。


    solution

    首先我们把所有点的权值写成W+x1 或W-x1的样子。

    那么每次询问就相当于挑两个点解方程。

    现在剩下修改。

    修改一个点,它对自己子树的贡献按深度为+1 -1 +1...

    一开始先dfs

    对于每一个点记一个op为 +1 -1

    统计时乘上系数即可。

    由于是区间修改,单点查询,可以ccj线段树或差分再树状数组实现

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define maxn 1000005
    #define ll long long
    using namespace std;
    int n,q,OP,head[maxn],f[maxn],w[maxn],tot;
    int dfst[maxn],dfsn[maxn],sc,op[maxn],val[maxn];
    int t1,t2,t3,li,ri,dy[maxn];
    struct node{
        int v,nex;
    }e[maxn];
    struct no{
        ll v;
    }tree[maxn*8];
    void lj(int t1,int t2){
        e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
    }
    void dfs(int k,int opt){
        dfst[k]=++sc;op[k]=opt;dy[sc]=k;
        for(int i=head[k];i;i=e[i].nex){
            val[e[i].v]=-val[k]+w[e[i].v];
            dfs(e[i].v,-opt);
        }
        dfsn[k]=sc;
    }
    void build(int k,int L,int R){
        if(L==R){
            tree[k].v=op[dy[L]]*val[dy[L]];return;
        }
        int mid=L+R>>1;
        build(k*2,L,mid);build(k*2+1,mid+1,R);
    }
    void ch(int k,int v,int l,int r){
         
        if(l>=li&&r<=ri){
            tree[k].v+=v;
            //cout<<"change "<<tree[k].l<<' '<<tree[k].r<<' '<<tree[k].v<<endl;
            return;
        }
        int mid=l+r>>1;
        if(li<=mid)ch(k*2,v,l,mid);
        if(ri>mid)ch(k*2+1,v,mid+1,r);
    }
    ll ask(int k,int pl,int opt,ll now,int l,int r){
        now+=opt*tree[k].v;
        if(l==r)return now;
        //cout<<tree[k].l<<' '<<tree[k].r<<' '<<now<<endl; 
        int mid=l+r>>1;
        if(pl<=mid)return ask(k*2,pl,opt,now,l,mid);
        else return ask(k*2+1,pl,opt,now,mid+1,r);
    }
    int get(){
        int v=0;char ch;
        while(!isdigit(ch=getchar()));v=v+ch-48;
        while(isdigit(ch=getchar()))v=(v<<3)+(v<<1)+ch-48;
        return v;
    }
    int main()
    {
        cin>>n>>q;
        for(int i=2;i<=n;i++){
            scanf("%d%d",&f[i],&w[i]);
            lj(f[i],i);
        }
        dfs(1,1);build(1,1,n);
        //for(int i=1;i<=n;i++)cout<<i<<' '<<val[i]<<' '<<op[i]<<endl;
        for(int i=1;i<=q;i++){
            scanf("%d",&OP);
            if(OP==1){
                scanf("%d%d%d",&t1,&t2,&t3);
                ll v1=ask(1,dfst[t1],op[t1],0,1,n),v2=ask(1,dfst[t2],op[t2],0,1,n);
                if(op[t1]+op[t2]==0){
                    if(v1+v2==t3)puts("inf");
                    else puts("none");
                }
                else {
                    ll tmp=t3-v1-v2;
                    if(tmp%2==0)printf("%lld
    ",tmp/2*op[t1]);
                    else puts("none");
                }
            }
            else {
                scanf("%d%d",&t1,&t2);
                li=dfst[t1],ri=dfsn[t1];
                ch(1,-op[t1]*w[t1],1,n);w[t1]=t2;
                ch(1,op[t1]*w[t1],1,n);
            }
        }
        return 0;
    }
  • 相关阅读:
    android的FATAL EXCEPTION: main错误
    ORA12560: TNS: 协议适配器错误
    BroadcastReceiver应用详解
    using C# 详解
    mysqlproxy0.8版本读写分离测试总结
    Mysql SHOW PROCESSLIST Sending data
    [转载]大型网站运维探讨和心得
    找出并optimization表
    mysql中普通索引和唯一索引的效率对比
    ps aux 中STAT 解释
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358775.html
Copyright © 2020-2023  润新知