題目大意:給定一棵以1為根的有根樹,每個節點有點權,提供兩種操作:
1.以某個節點為根的子樹所有節點權值+x
2.求一些鏈的並集的點權和,其中這些鏈都是由某個節點出發指向根
首先子樹修改,鏈上查詢,樹鏈剖分的wt~
然後這些鏈上的每個點的點權都只能被加一次,肯定不能打標記,由於k<=5,我們考慮容斥原理
總權值=單鏈-兩兩之交+三鏈之交……
狀壓列舉即可 兩條鏈的交集求法如下:
1.求兩條鏈底的lca
2.若lca的深度小於其中一條鏈的鏈頂深度 交集為空 返回0
3.返回一條鏈 鏈底為lca 鏈頂為兩條鏈頂中深度較大的那個
此題mod2^31,直接自然溢位int,然後答案對2147483647取與即可 出題人真貼心-。-
時間複雜度o( m * log^2n * 2^k ) 看到這複雜度我都尿了0.0 不tle真是太好了
#include#include#include#include#define m 200200
#define ls tree[p].lson
#define rs tree[p].rson
using namespace std;
struct abcdtable[m<<1];
struct treetree[m<<1];int tree_tot;
int head[m],tot;
int n,m,k;
int fa[m],son[m],dpt[m],siz[m],top[m],pos[m],cnt;
int digit[m];
pairbr[10];
void build_tree(int p,int x,int y)
void modify(int p,int x,int y,int l,int r,int v)
if(tree[p].mark)
if(r<=mid)
modify(ls,x,mid,l,r,v);
else if(l>mid)
modify(rs,mid+1,y,l,r,v);
else modify(ls,x,mid,l,mid,v) , modify(rs,mid+1,y,mid+1,r,v);
tree[p].num=tree[ls].num+tree[rs].num;
}int get_ans(int p,int x,int y,int l,int r)
if(r<=mid) return get_ans(ls,x,mid,l,r);
if(l>mid) return get_ans(rs,mid+1,y,l,r);
return get_ans(ls,x,mid,l,mid) + get_ans(rs,mid+1,y,mid+1,r);
}void dfs1(int x)
}void dfs2(int x)
}void add(int x,int y)
int query(int x,int y)
int calculate(int x)
return query(re.first,re.second);
}int inclusion_exclusion_principle()
else
printf("%d\n", inclusion_exclusion_principle()&2147483647 );
} }}
樹鏈剖分 BZOJ3589 動態樹
time limit 30 sec memory limit 1024 mb submit 543 solved 193 submit status discuss 別忘了這是一棵動態樹,每時每刻都是動態的.小明要求你在這棵樹上維護兩種事件 事件0 這棵樹長出了一些果子,即某個子樹中的每個節點都會長...
bzoj 3589 動態樹 (樹鏈剖分 線段樹)
time limit 30 sec memory limit 1024 mb submit 451 solved 155 submit status discuss 別忘了這是一棵動態樹,每時每刻都是動態的.小明要求你在這棵樹上維護兩種事件 事件0 這棵樹長出了一些果子,即某個子樹中的每個節點都會長...
BZOJ 3589 動態樹 樹鏈剖分 線段樹
題目傳送門 最近心真的有點浮躁啊 連題目都不想好好看了 於是就把 一條樹枝其實就是乙個從某個節點到根的路徑的一段 看成了 一條樹枝其實就是乙個從某個節點到根的路徑 wqnmlgb 操作1的k 5 那麼是不是會想到容斥?對兩條路徑求交?但是分析一下時間複雜度,o m log22n 2k 接近20億啊 ...