标签:logs scanf namespace ota 地址 work oid tip scan
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6162
题目:
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 526 Accepted Submission(s): 177
思路:
裸的树链剖分套主席树。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define MP make_pair 6 #define PB push_back 7 typedef long long LL; 8 typedef pair<int,int> PII; 9 const double eps=1e-8; 10 const double pi=acos(-1.0); 11 const int K=1e5+100; 12 const int mod=1e9+7; 13 14 vector<int>mp[K]; 15 int top[K],sz[K],fa[K],son[K],id[K],hid[K],deep[K]; 16 int cnt,n,q; 17 18 void dfs1(int x,int f) 19 { 20 sz[x]=1,fa[x]=f,son[x]=-1,deep[x]=deep[f]+1; 21 for(int i=0;i<mp[x].size();i++) 22 if(mp[x][i]!=f) 23 { 24 dfs1(mp[x][i],x); 25 sz[x]+=sz[mp[x][i]]; 26 if(son[x]==-1||sz[son[x]]<sz[mp[x][i]]) 27 son[x]=mp[x][i]; 28 } 29 } 30 void dfs2(int x,int f) ///每条边用深度大的节点的序号表示 31 { 32 top[x]=f,id[x]=++cnt,hid[id[x]]=x; 33 if(son[x]!=-1) dfs2(son[x],f); 34 for(int i=0;i<mp[x].size();i++) 35 if(mp[x][i]!=fa[x]&&mp[x][i]!=son[x]) 36 dfs2(mp[x][i],mp[x][i]); 37 } 38 39 int tot,ls[K*20],rs[K*20],rt[K*20]; 40 int a[K],b[K]; 41 LL sum[K*20]; 42 //sum[o]记录的是该节点区间内出现的数的和 43 //区间指的是将数离散化后的区间 44 void build(int &o,int l,int r) 45 { 46 o=++tot,sum[o]=0; 47 int mid=l+r>>1; 48 if(l!=r) 49 build(ls[o],l,mid),build(rs[o],mid+1,r); 50 } 51 void update(int &o,int l,int r,int last,int x) 52 { 53 o=++tot,sum[o]=sum[last]+b[x]; 54 ls[o]=ls[last],rs[o]=rs[last]; 55 if(l==r) return ; 56 int mid=l+r>>1; 57 if(x<=mid) update(ls[o],l,mid,ls[last],x); 58 else update(rs[o],mid+1,r,rs[last],x); 59 } 60 LL query(int lo,int ro,int l,int r,int k) 61 { 62 if(k<1) return 0; 63 if(r<=k) return sum[ro]-sum[lo]; 64 int mid=l+r>>1; 65 if(k<=mid) return query(ls[lo],ls[ro],l,mid,k); 66 return query(rs[lo],rs[ro],mid+1,r,k)+sum[ls[ro]]-sum[ls[lo]]; 67 } 68 LL tree_query(int x,int y,int l,int r,int sz) 69 { 70 LL ret=0; 71 while(top[x]!=top[y]) 72 { 73 if(deep[top[x]]<deep[top[y]]) swap(x,y); 74 ret+=query(rt[id[top[x]]-1],rt[id[x]],1,sz,r)-query(rt[id[top[x]]-1],rt[id[x]],1,sz,l-1); 75 x=fa[top[x]]; 76 } 77 if(deep[x]>deep[y]) swap(x,y); 78 ret+=query(rt[id[x]-1],rt[id[y]],1,sz,r)-query(rt[id[x]-1],rt[id[y]],1,sz,l-1); 79 return ret; 80 } 81 int main(void) 82 { 83 //freopen("in.acm","r",stdin); 84 //freopen("out.acm","w",stdout); 85 while(~scanf("%d%d",&n,&q)) 86 { 87 cnt=tot=0; 88 memset(mp,0,sizeof mp); 89 for(int i=1;i<=n;i++) scanf("%d",a+i),b[i]=a[i]; 90 for(int i=1,x,y;i<n;i++) 91 scanf("%d%d",&x,&y),mp[x].PB(y),mp[y].PB(x); 92 sort(b+1,b+1+n); 93 int sz=unique(b+1,b+1+n)-b-1; 94 for(int i=1;i<=n;i++) 95 a[i]=lower_bound(b+1,b+1+sz,a[i])-b; 96 dfs1(1,0); 97 dfs2(1,0); 98 build(rt[0],1,sz); 99 for(int i=1;i<=n;i++) 100 update(rt[i],1,sz,rt[i-1],a[hid[i]]); 101 // for(int i=1;i<=n;i++) 102 // printf("id[%d]=%d ",i,id[i]); 103 // printf("\n"); 104 for(int i=1,u,v,l,r,tmp;i<=q;i++) 105 { 106 scanf("%d%d%d%d",&u,&v,&l,&r); 107 l=lower_bound(b+1,b+1+sz,l)-b; 108 tmp=lower_bound(b+1,b+1+sz,r)-b; 109 if(b[tmp]>r||tmp>sz) r=tmp-1; 110 else r=tmp; 111 printf("%lld%c",tree_query(u,v,l,r,sz),i==q?‘\n‘:‘ ‘); 112 } 113 } 114 return 0; 115 }
标签:logs scanf namespace ota 地址 work oid tip scan
原文地址:http://www.cnblogs.com/weeping/p/7414504.html