Equation

  调了半个下午啊。
  基本上所有人都是正解;
  自闭了。
  考场上想出来了同一条链上的点互相间都可以有方程。
  但是不自信能想出正解。
  就想高斯消元,结果挂了。
  正解是根据我刚刚说的那个性质,可以发现1与所有点都共链,那么所有未知数都可以用1的变量来表示。
  得到额外的方程后,先看方程里的未知数用\(x_1\)表示的形式加和是不是给出的数,若是,那么此时\(x_1\)被消掉,只有\(n-1\)个有效方程,是无穷解,若不相同,就是无解。
  若一消不掉,就可以解出了。
  但有个细节,题中说所有未知数是整数,就意味着若解是实型,也算无解。
  至于说修改,其实当所有未知量用1表示时都有另外一个加数\(b\),是可以求的,有规律,懒得写了,很好推。
  对于这个\(b\)可以做差分树状数组。
  以\(DFS\)序为下表建立数组。
  奇数偶数要分开考虑,因为奇偶性不同,同一个数的系数正负不同,区间修改时加的数就不同。

Code
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
	#define rr register 
	typedef long long ll;
	const int N=1e6+4;
	int n,q;
	int to[N],dire[N],head[N],fa[N];
	int size[N],depth[N],w[N];
	int id[N],reid[N],w_[N];
	inline void add(int f,int t)
	{
		static int num=0;
		to[++num]=t;
		dire[num]=head[f];
		head[f]=num;
	}
	int read()
	{
		rr int x_read=0,y_read=1;
		rr char c_read=getchar();
		while(c_read<'0'||c_read>'9')
		{
			if(c_read=='-') y_read=-1;
			c_read=getchar();
		}
		while(c_read<='9'&&c_read>='0')
		{
			x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
			c_read=getchar();
		}
		return x_read*y_read;
	}
	class tree_a
	{
		private:
			ll a[N];
			inline int lowbit(int x){return x&(-x);}
		public:
			void insert(int,int);
			ll query(int,int);
	}t[2];
	void tree_a::insert(int pos,int val)
	{
		while(pos<=n)
		{
			a[pos]+=val;
			pos+=lowbit(pos);
		}
	}
	ll tree_a::query(int l,int r)
	{
		ll sum=0;
		while(r)
		{
			sum+=a[r];
			r-=lowbit(r);
		}
		while(l)
		{
			sum-=a[l];
			l-=lowbit(l);
		}
		return sum;
	}
	void dfs(int x)
	{
		static int num=0;
		size[x]=1;
		id[x]=++num;
		reid[num]=x;
		for(rr int i=head[x];i;i=dire[i])
		{
			depth[to[i]]=depth[x]+1;
			w[to[i]]-=w[x];
			dfs(to[i]);
			size[x]+=size[to[i]];
		}
	}
};
using namespace STD;
int main()
{
	n=read(),q=read();
	for(rr int i=2;i<=n;i++)
	{
		fa[i]=read();
		w_[i]=w[i]=read();
		add(fa[i],i);
	}
	dfs(1);
	for(rr int i=1;i<=n;i++)
	{
		t[depth[i]&1].insert(id[i],w[i]-w[reid[id[i]-1]]);
		t[(depth[i]&1)^1].insert(id[i],w[i]-w[reid[id[i]-1]]);
	}
	while(q--)
	{
		int opt=read();
		if(opt==1)
		{
			int u=read(),v=read(),s=read();
			int a1=(depth[u]&1)?-1:1;
			int a2=(depth[v]&1)?-1:1;
			ll b1=0,b2=0;
			b1=t[depth[u]&1].query(0,id[u]);
			b2=t[depth[v]&1].query(0,id[v]);
			if(a1!=a2)
			{
				if(b1+b2==s) printf("inf\n");
				else printf("none\n");
			}
			else
			{
				a1+=a2;
				b1+=b2;
				if((s-b1)%a1) printf("none\n");
				else printf("%lld\n",(s-b1)/a1);
			}
		}
		else
		{
			int u=read(),v=read();
			int u_=u;
			t[depth[u_]&1].insert(id[u_],v-w_[u_]);
			t[(depth[u_]&1)^1].insert(id[u_],w_[u_]-v);
			t[depth[u_]&1].insert(id[u_]+size[u_],w_[u_]-v);
			t[(depth[u_]&1)^1].insert(id[u_]+size[u_],v-w_[u_]);
			w_[u_]=v;
		}
	}
}

2021-08-09 20:47:16 星期一

posted @ 2021-08-09 20:48  Geek_kay  阅读(183)  评论(0编辑  收藏  举报