Hdu 2665
区间K小
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
int arr[maxn];
int Rank[maxn];
struct ChairTree{
#define lson tree[rt].lc,tree[rt1].lc,l,m
#define rson tree[rt].rc,tree[rt1].rc,m+1,r
struct node{
int lc,rc,w;
node(){}
}tree[maxn*20];
int root[maxn],cnt;
void init(){
root[0]=cnt=0;
memset(tree,0,sizeof tree);
}
void add(int pos,int val,int &rt,int rt1,int l,int r){
tree[rt = ++cnt] = tree[rt1];
tree[rt].w += val;
if(l==r) return;
int m=(l+r)/2;
if(pos<=m) add(pos,val,lson);
else add(pos,val,rson);
}
int query(int k,int rt,int rt1,int l,int r){
if(l==r) return l;
int lsize = tree[tree[rt1].lc].w-tree[tree[rt].lc].w;
int m=(l+r)/2;
if(lsize>=k) return query(k,lson);
else return query(k-lsize,rson);
}
}T;
int main(){
//freopen("in.txt","r",stdin);
int cas,n,q,l,r,k;
for(cin>>cas;cas--;){
T.init();
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
Rank[i]=arr[i];
}
sort(Rank+1,Rank+1+n);
int un=unique(Rank+1,Rank+1+n)-(Rank+1);
for(int i=1;i<=n;i++){
arr[i]=lower_bound(Rank+1,Rank+1+un,arr[i])-Rank;
}
for(int i=1;i<=n;i++){
T.add(arr[i],1,T.root[i],T.root[i-1],1,un);
}
while(q--){
scanf("%d%d%d",&l,&r,&k);
int pos = T.query(k,T.root[l-1],T.root[r],1,un);
printf("%d
",Rank[pos]);
}
}
return 0;
}
hdu 6162
多校9的题,因为数据弱水过去了。
考虑主席树,用dfs的方式建立主席树。
设$lca(u,v)=f$,那么路径就是f到u+f到v的满足条件的和。
主席树区间查询。那么答案就是f到u和fa[f]到v。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
int arr[maxn];
int Rank[maxn];
vector<int> e[maxn];
int dep[maxn],fa[maxn][18];
int cas,n,q,l,r,k;
struct ChairTree{
#define sum(x) tree[x].sum
#define lson tree[rt].lc,tree[rt1].lc,l,m
#define rson tree[rt].rc,tree[rt1].rc,m+1,r
struct node{
int lc,rc;
ll sum;
node(){}
}tree[maxn*20];
int root[maxn],cnt,n;
void init(int _n){
n=_n;
root[0]=cnt=0;
memset(tree,0,sizeof tree);
}
void add(int pos,int val,int &rt,int rt1,int l,int r){
tree[rt = ++cnt] = tree[rt1];
tree[rt].sum += val;
if(l==r) return;
int m=(l+r)/2;
if(pos<=m) add(pos,val,lson);
else add(pos,val,rson);
}
ll query(int L,int R,int rt,int rt1,int l,int r){
if(L<=l&&r<=R) return sum(rt1)-sum(rt);
if(0==sum(rt1)) return 0;
ll ret=0;
int m=(l+r)/2;
if(L<=m) ret+=query(L,R,lson);
if(m< R) ret+=query(L,R,rson);
return ret;
}
}T;
void dfs(int id,int father){
T.add(arr[id],Rank[arr[id]],T.root[id],T.root[father],1,n);
fa[id][0]=father;
dep[id]=dep[father]+1;
for(int i=1;i<=17;i++){
if(dep[id]<(1<<i)) break;
fa[id][i]=fa[fa[id][i-1]][i-1];
}
for(auto ep:e[id]){
if(ep==father) continue;
dfs(ep,id);
}
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int t=dep[x]-dep[y];
for(int i=0;i<=17;i++) if((1<<i)&t) x=fa[x][i];
for(int i=17;i>=0;i--)
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];y=fa[y][i];
}
return x==y?x:fa[x][0];
}
ll solve(int u,int v,int L,int R){
int f=lca(u,v);
int ff=fa[f][0];
//cout<<ff<<"#
";
ll ret=0;
ret += T.query(L,R,T.root[f],T.root[u],1,n);
//cout<<ret<<"#
";
ret += T.query(L,R,T.root[ff],T.root[v],1,n);
//cout<<ret<<"#
";
return ret;
}
int main(){
//freopen("in.txt","r",stdin);
for(;~scanf("%d%d",&n,&q);){
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
Rank[i]=arr[i];
}
sort(Rank+1,Rank+1+n);
int un=unique(Rank+1,Rank+1+n)-(Rank+1);
for(int i=1;i<=n;i++){
arr[i]=lower_bound(Rank+1,Rank+1+un,arr[i])-Rank;
}
for(int i=1;i<=n;i++)
e[i].clear();
memset(fa,0,sizeof fa);
memset(dep,0,sizeof dep);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
T.init(n);
dfs(1,0);
int u,v;
while(q--){
scanf("%d%d%d%d",&u,&v,&l,&r);
int L=lower_bound(Rank+1,Rank+1+un,l)-Rank;
if(Rank[L]<l) L++;
int R=lower_bound(Rank+1,Rank+1+un,r)-Rank;
if(R>un||Rank[R]>r) R--;
//cout<<"#"<<L<<" "<<R<<endl;
ll res=solve(u,v,L,R);
printf("%lld%c",res,"
"[q==0]);
}
}
return 0;
}
Codeforces Edu 33 F
主席树,按照dfs先后从根向前合并线段树。线段树维护dep的最小值。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int arr[maxn];
int Rank[maxn],n,rtt;
int dep[maxn];
vector<int> e[maxn];
struct ChairTree{
#define lson tree[rt].lc,tree[rt1].lc,l,m
#define rson tree[rt].rc,tree[rt1].rc,m+1,r
struct node{
int lc,rc,w;
node(){}
}tree[maxn*20];
int root[maxn],cnt;
void init(){
root[0]=cnt=0;
memset(tree,0,sizeof tree);
}
int merge(int rt,int rt1,int l,int r){
if(!rt1) return rt;
if(!rt) return rt1;
int z=++cnt;
if(l==r){
tree[z].w=min(tree[rt].w,tree[rt1].w);
return z;
}
int m=(l+r)/2;
tree[z].lc=merge(lson);
tree[z].rc=merge(rson);
if(tree[z].lc||tree[z].rc) tree[z].w=min(tree[tree[z].lc].w,tree[tree[z].rc].w);
else tree[z].w=min(tree[rt].w,tree[rt1].w);
return z;
}
void add(int pos,int val,int &rt,int rt1,int l,int r){
rt=++cnt;
if(l==r){
tree[rt].w=val;
return;
}
int m=(l+r)>>1;
if(pos<=m) add(pos,val,lson);
else add(pos,val,rson);
tree[rt].w=min(tree[tree[rt].lc].w,tree[tree[rt].rc].w);
}
int query(int L,int R,int rt,int rt1,int l,int r){
if(L<=l&&r<=R) return tree[rt].w;
int m=(l+r)/2;
if(m>=R) return query(L,R,lson);
else if(m<L) return query(L,R,rson);
else return min(query(L,R,lson),query(L,R,rson));
}
}T;
void dfs(int id,int fa){
dep[id]=dep[fa]+1;
T.add(dep[id],arr[id],T.root[id],T.root[fa],1,n);
for(auto ep:e[id]){
if(ep==fa) continue;
dfs(ep,id);
T.root[id]=T.merge(T.root[id],T.root[ep],1,n);
}
}
int main(){
//freopen("input.txt","r",stdin);
T.tree[0].w=INT_MAX;
scanf("%d%d",&n,&rtt);
for(int i=1;i<=n;i++)
scanf("%d",arr+i);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
dep[0]=0;
dfs(rtt,0);
int la=0,x,k;
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&k);
x=(x+la)%n+1;
k=(k+la)%n;
//printf("%d %d
",x,k);
la=T.query(dep[x],min(dep[x]+k,n),T.root[x],T.root[x],1,n);
printf("%d
",la);
}
return 0;
}