标签:mis should lower 分析 opera either scan == style
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 662 Accepted Submission(s): 229
【题意】给你一棵树,每个节点有一个权值,M次询问,给出u,v,a,b,求权值在区间[a,b]中的和。
【分析】数据实在是太水了,暴力都能过,这里说一下正确的树剖,离线往线段树插值得写法。将每个询问分成两部分,[1,b]-[1,a-1],放进一个 集合排序,从小到大取出,将节点权值同样 排序,若当前权值<=询问中的权值,则插入线段树。
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define met(a,b) memset(a,b,sizeof a) #define pb push_back #define mp make_pair #define lson(x) ((x<<1)) #define rson(x) ((x<<1)+1) #define rep(i,l,r) for(int i=(l);i<=(r);++i) #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 1e5+50;; const int M = 17; const int mod = 2520; const int mo=123; const double pi= acos(-1.0); typedef pair<int,int>pii; int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N]; int num,n,m; ll ans[N]; vector<int>edg[N]; vector<pii>vec; struct query{ int u,v,x,id; bool operator <(const query &d)const{ return x<d.x; } }q[N*2]; void dfs1(int u, int f, int d) { dep[u] = d; siz[u] = 1; son[u] = 0; fa[u] = f; for (int v : edg[u]) { if (v == f) continue; dfs1(v, u, d + 1); siz[u] += siz[v]; if (siz[son[u]] < siz[v]) son[u] = v; } } void dfs2(int u, int tp) { top[u] = tp; id[u] = ++num; if (son[u]) dfs2(son[u], tp); for (int v : edg[u]) { if (v == fa[u] || v == son[u]) continue; dfs2(v, v); } } struct Tree { int l,r; ll sum; }; Tree tree[4*N]; void pushup(int x) { tree[x].sum=tree[lson(x)].sum+tree[rson(x)].sum; } void build(int l,int r,int v) { tree[v].l=l; tree[v].r=r; if(l==r) { tree[v].sum=0; return ; } int mid=(l+r)>>1; build(l,mid,v*2); build(mid+1,r,v*2+1); pushup(v); } void update(int o,int v,int val) { if(tree[o].l==tree[o].r) { tree[o].sum= val; return ; } int mid = (tree[o].l+tree[o].r)/2; if(v<=mid) update(o*2,v,val); else update(o*2+1,v,val); pushup(o); } ll querySum(int x,int l,int r) { if (tree[x].l >= l && tree[x].r <= r) { return tree[x].sum; } int mid = (tree[x].l + tree[x].r) / 2; ll ans = 0; if (l <= mid) ans += querySum(lson(x),l,r); if (r > mid) ans += querySum(rson(x),l,r); return ans; } ll Qsum(int u,int v) { int tp1 = top[u], tp2 = top[v]; ll ans = 0; while (tp1 != tp2) { if (dep[tp1] < dep[tp2]) { swap(tp1, tp2); swap(u, v); } ans +=querySum(1,id[tp1], id[u]); u = fa[tp1]; tp1 = top[u]; } if (dep[u] > dep[v])swap(u, v); ans +=querySum(1,id[u], id[v]); return ans; } void init(){ for(int i=0;i<N;i++)edg[i].clear(); met(tree,0);met(son,0);vec.clear();met(ans,0); } int main() { while(~scanf("%d%d",&n,&m)) { init(); for(int i=1,x; i<=n; i++)scanf("%d",&x),vec.pb(mp(x,i)); for(int i=1,u,v; i<n; i++) { scanf("%d%d",&u,&v); edg[u].pb(v);edg[v].pb(u); } num = 0; dfs1(1,0,1); dfs2(1,1); sort(vec.begin(),vec.end()); for(int i=1;i<=m;i++){ int x,y,a,b; scanf("%d%d%d%d",&x,&y,&a,&b); q[i]=query{x,y,a-1,-i}; q[i+m]=query{x,y,b,i}; } sort(q+1,q+2*m+1); int now=0; build(1,num,1); for(int i=1;i<=2*m;i++){ while(now<n&&vec[now].first<=q[i].x){ update(1,id[vec[now].second],vec[now].first); now++; } ans[abs(q[i].id)]+=Qsum(q[i].u,q[i].v)*(q[i].id>0?1:-1); } for(int i=1;i<=m;i++)printf("%lld%c",ans[i],i==m?‘\n‘:‘ ‘); } return 0; }
HDU 6162 Ch’s gift (树剖 + 离线线段树)
标签:mis should lower 分析 opera either scan == style
原文地址:http://www.cnblogs.com/jianrenfang/p/7417297.html