牛客競賽&&mjt的毒瘤賽
阿新 • • 發佈:2019-02-09
space d+ oid bool printf ack clas 查詢 cto
題目鏈接
https://ac.nowcoder.com/acm/contest/368/F
思路,代碼
/* 詢問可以離線。 然後每個節點上建32個權值線段樹(權值不大,其實只要20顆) 記錄每一位權值為x(如果是根節點的話)的01和 然後從根節點向上合並。 訪問到需要訪問的就查詢。 大體這樣,不過細節和處理極其惡心(毒瘤mjt或者我碼力太差) 合並的時候。 因為兩個數字相同要,合並到底的時候要這樣 if(!siz[a]&&!siz[b]) return a; if(siz[a]==siz[b]) { for(int i=0;i<=20;++i) xo[a][i]=0; siz[a]=0;siz[b]=0; } else { for(int i=0;i<=20;++i) xo[a][i]=(bool)((1<<i)&l); siz[a]=1,siz[b]=0; } return a; 因為要異或上x,所以就要討論子樹中0的個數,因為出現兩個的樹的刪去了,還要維護siz 空間\時間復雜度是$nlog^2$ */ #include<bits/stdc++.h> using namespace std; const int N=2e5+7; vector<int> G[N]; int n,m,w[N],cnt; long long ans[N]; vector<pair<int,int> > Q[N]; int ls[N*20],rs[N*20],xo[N*20][21],rt[N*20],siz[N*20]; void pushup(int rt) { for(int i=0;i<=20;++i) xo[rt][i]=xo[ls[rt]][i]+xo[rs[rt]][i]; siz[rt]=siz[ls[rt]]+siz[rs[rt]]; } int zibi; int merge(int l,int r,int a,int b) { if(!a||!b) return a+b; if(l==r) { if(!siz[a]&&!siz[b]) return a; if(siz[a]==siz[b]) { for(int i=0;i<=20;++i) xo[a][i]=0; siz[a]=0;siz[b]=0; } else { for(int i=0;i<=20;++i) xo[a][i]=(bool)((1<<i)&l); siz[a]=1,siz[b]=0; } return a; } int mid=(l+r)>>1; ls[a]=merge(l,mid,ls[a],ls[b]); rs[a]=merge(mid+1,r,rs[a],rs[b]); pushup(a); return a; } void insert(int &now,int l,int r,int k) { now=++cnt; if(l==r) { for(int i=0;i<=20;++i) xo[now][i]=(bool)((1<<i)&k); siz[now]=1; return; } int mid=(l+r)>>1; if(k<=mid) insert(ls[now],l,mid,k); else insert(rs[now],mid+1,r,k); pushup(now); } int query(int l,int r,int k,int dep,int rt) { if(!rt||r<=k) return 0; if(l>k) return xo[rt][dep]; int mid=(l+r)>>1; // int ans=0; if(k<=mid) return query(mid+1,r,k,dep,rs[rt])+query(l,mid,k,dep,ls[rt]); // if(k>mid) return query(mid+1,r,k,dep,rs[rt]); } int query_siz(int l,int r,int k,int rt) { if(!rt||r<=k) return 0; if(l>k) return siz[rt]; int mid=(l+r)>>1; // int ans=0; if(k<=mid) return query_siz(mid+1,r,k,rs[rt])+query_siz(l,mid,k,ls[rt]); // if(k>mid) return query_siz(mid+1,r,k,rs[rt]); } void dfs(int u,int f) { insert(rt[u],1,n,w[u]); for(vector<int>::iterator it=G[u].begin();it!=G[u].end();++it) { if(*it==f) continue; dfs(*it,u); rt[u]=merge(1,n,rt[u],rt[*it]); } for(vector<pair<int,int> >::iterator it=Q[u].begin();it!=Q[u].end();++it) { for(int i=0;i<=20;++i) { int js=query_siz(1,n,it->first,rt[u]); if(it->first&(1<<i)) { ans[it->second]+=(1LL<<i)*(long long)(js-query(1,n,it->first,i,rt[u])); } else { ans[it->second]+=(1LL<<i)*(long long)query(1,n,it->first,i,rt[u]); } } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&w[i]); for(int i=2;i<=n;++i) { int a,b; scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } for(int i=1;i<=m;++i) { int u,x; scanf("%d%d",&u,&x); Q[u].push_back(make_pair(x,i)); } dfs(1,0); for(int i=1;i<=m;++i) printf("%lld\n",ans[i]); return 0; }
牛客競賽&&mjt的毒瘤賽