[雅礼NOIP2018集训] day6

打满暴力好像是一种挑战,已经连续几天考试最后一个小时自闭了,因为自以为打完了暴力,然而,结果往往差强人意

大概是考试的策略有些问题


T1:

待填


T2:

考虑到,一开始的形如$x_i+x_fa=w$形成一棵以1为根节点的树,也就是说任意的点都可以用$x_1$表示

设1为偶数点,那么奇数点都可以表示成形如$k-x_i$的形式,偶数点都可以表示为形如$k+x_1$的形式

考虑操作1:我们假设已知$x_u,x_v$用$x_i$的表示和$u,v$是奇数点还是偶数点,分以下情况讨论

1.两个都是奇数点,那么有$k_u-x_1+k_v-x_1=s$,移项得到$2x_1=s+k_u+k_v$,计算答案就好

2.两个都是偶数点,那么有$k_u+x_1+k_v+x_1=s$,移项得到$2x_1=s-k_u-k_v$,计算答案就好

3.一个是奇数点,一个是偶数点,这样的话$x_1$就会消掉,判断得到的结果与给定的s是否相同即可

显然初始化一遍dfs每个点的表示和奇偶都可以轻易得到

考虑操作2如何维护?

我们发现改变一个点与其父亲的$w$值最终改变表达的只是这个点子树里的点,我们把奇数点和偶数点分情况讨论,用树状数组维护区间加就好

如当前点已知表达为$x$,接下来的表达分别为$w_1-x,w_2-w_1+x,w_3-w_2+w_1-x$

总结起来就是奇到奇是+,偶到偶是+,奇到偶和偶到奇都是-(这个主要是方便笔者自己理解...可能有点抽象,感性理解一下)

std用了很神奇的一个树状数组同时解决了奇点和偶点的修改,用的就是上述的性质

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;

const int N=1e6+15;
int n,q,tot,tim;
int head[N],dep[N],dfn[N],edfn[N],t[N],w[N];
struct EDGE
{
    int to,nxt,ww;
}edge[N];
inline int read()
{
    char ch=getchar();
    int s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
void ad(int u,int v,int ww)
{
    edge[++tot]=(EDGE){v,head[u],ww};
    head[u]=tot;
}
void dfs(int x)
{
    dfn[x]=++tim;
    for (int i=head[x];i;i=edge[i].nxt)
    {
        int y=edge[i].to;
        dep[y]=dep[x]^1;
        dfs(y);
    }
    edfn[x]=tim;
}
void add(int x,int y)
{
    while (x<=n)
    {
        t[x]+=y;
        x+=x&-x;
    }
}
int sum(int x)
{
    int re=0;
    while (x)
    {
        re+=t[x];
        x-=x&-x;
    }
    return re;
}
int main()
{
//    freopen("equation.in","r",stdin);
//    freopen("equation.out","w",stdout);
    n=read();q=read();
    for (int i=2,u;i<=n;i++)
    {
        u=read();w[i]=read();
        ad(u,i,w[i]);
    }
    dfs(1);
    for (int i=2;i<=n;i++) if (!dep[i]) w[i]=-w[i];
    for (int i=2;i<=n;i++) {add(dfn[i],w[i]);add(edfn[i]+1,-w[i]);}
    while (q--)
    {
        int opt=read();
        if (opt==1)
        {
            int u=read(),v=read(),s=read();
            int x=sum(dfn[u]),y=sum(dfn[v]);
            if (dep[u]&&dep[v])
            {
                ll rt=1ll*x+y-s;
                if (rt%2!=0) puts("none");
                else printf("%lld\n",rt/2);
            }
            else if (!dep[u]&&!dep[v])
            {
                ll rt=1ll*x+y+s;
                if (rt%2!=0) puts("none");
                else printf("%lld\n",rt/2);
            }
            else 
            {
                if (!dep[u]) swap(u,v),swap(x,y);
                if (x-y==s) puts("inf");
                else puts("none");
            }
        }
        if (opt==2)
        {
            int u=read(),ww=read();
            if (!dep[u]) ww=-ww;
            add(dfn[u],ww-w[u]);add(edfn[u]+1,w[u]-ww);
            w[u]=ww;
        }
    }
    return 0;
} 
View Code

T3:

待填

猜你喜欢

转载自www.cnblogs.com/xxzh/p/9748156.html