标签:art print tin lca har operator 统计 get 主席树
题面:https://www.cnblogs.com/Juve/articles/11655531.html
三道数据结构?
d:
贪心,先按a排序,然后枚举删了前i个a值比较小的,然后在剩下的里面删m-i个b小的,然后统计答案
用主席树查b排名(m-i+1)或用堆维护b
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define int long long using namespace std; const int MAXN=1e5+5; int read(){ int x=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();} return x; } int t,n,m,ans; struct node{ int a,b; friend bool operator < (node p,node q){ return p.a<q.a; } }sq[MAXN]; priority_queue<int>q; signed main(){ t=read(); while(t--){ n=read(),m=read(); ans=0; for(int i=1;i<=n;++i) sq[i].a=read(),sq[i].b=read(); sort(sq+1,sq+n+1); while(!q.empty()) q.pop(); for(int i=m+1;i<=n;++i) q.push(-sq[i].b); for(int i=m;i>=0;--i){ int mx=-q.top(); ans=max(ans,mx*sq[i+1].a); if(sq[i].b>mx){ q.pop(); q.push(-sq[i].b); } } printf("%lld\n",ans); } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define int long long using namespace std; const int MAXN=1e5+5; int read(){ int x=0;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();} return x; } int t,n,m,ans,mx=0; struct node{ int a,b; friend bool operator < (node p,node q){ return p.a<q.a; } }sq[MAXN]; int root[MAXN],tot=0; struct chairman_tree{ int ls,rs,val; }tr[MAXN<<6]; void insert(int &now,int pre,int l,int r,int pos){ now=++tot;tr[now]=tr[pre];++tr[now].val; if(l==r) return ; int mid=(l+r)>>1; if(pos<=mid) insert(tr[now].ls,tr[pre].ls,l,mid,pos); else insert(tr[now].rs,tr[pre].rs,mid+1,r,pos); } int query(int x,int y,int l,int r,int num){ if(l==r) return l; int sum=tr[tr[y].ls].val-tr[tr[x].ls].val,mid=(l+r)>>1; if(sum>=num) return query(tr[x].ls,tr[y].ls,l,mid,num); else return query(tr[x].rs,tr[y].rs,mid+1,r,num-sum); } signed main(){ t=read(); while(t--){ n=read(),m=read(); ans=tot=mx=0; for(int i=1;i<=n;++i) sq[i].a=read(),sq[i].b=read(),mx=max(mx,sq[i].b); sort(sq+1,sq+n+1); for(int i=1;i<=n;++i) insert(root[i],root[i-1],1,mx,sq[i].b); for(int i=0;i<=m;++i) ans=max(ans,sq[i+1].a*query(root[i],root[n],1,mx,m-i+1)); printf("%lld\n",ans); } return 0; }
e:
开始学习主席树上树
不难看出是在每个询问点到所有询问点的lca路径上的前趋后继,然后就打的测试点分治和暴力
新知识:树上主席树,维护每个节点到根的前缀主席树,然后区间查询前趋后继
查前趋:
当前mid比val大,去右区间查找,但是会有一种情况:val等于mid+1,但主席树中没有mid+1,这时特判一下去找左区间
后继同理
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
int read(){
int x=0;char ch=getchar();
while(ch<‘0‘||ch>‘9‘) ch=getchar();
while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();}
return x;
}
const int MAXN=1e5+5;
int n,q,typ,a[MAXN],ans=0,p[MAXN],b[MAXN],mx;
int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
void add(int u,int v){
++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
}
int root[MAXN],tot=0;
struct node{
int ls,rs,val;
}tr[MAXN<<6];
void insert(int &now,int pre,int l,int r,int val){
now=++tot;tr[now]=tr[pre],++tr[now].val;
if(l==r) return ;
int mid=(l+r)>>1;
if(val<=mid) insert(tr[now].ls,tr[pre].ls,l,mid,val);
else insert(tr[now].rs,tr[pre].rs,mid+1,r,val);
}
int get_pre(int x,int y,int l,int r,int val){
if(tr[y].val-tr[x].val==0) return 0;
if(l==r) return l;
int mid=(l+r)>>1,res=0;
if(val>mid){
res=get_pre(tr[x].rs,tr[y].rs,mid+1,r,val);
if(res==0) res=get_pre(tr[x].ls,tr[y].ls,l,mid,val);
}else res=get_pre(tr[x].ls,tr[y].ls,l,mid,val);
return res;
}
int get_nxt(int x,int y,int l,int r,int val){
if(tr[y].val-tr[x].val==0) return 0;
if(l==r) return l;
int mid=(l+r)>>1,res=0;
if(val<=mid){
res=get_nxt(tr[x].ls,tr[y].ls,l,mid,val);
if(res==0) res=get_nxt(tr[x].rs,tr[y].rs,mid+1,r,val);
}else res=get_nxt(tr[x].rs,tr[y].rs,mid+1,r,val);
return res;
}
int deep[MAXN],fa[MAXN],siz[MAXN],son[MAXN];
void dfs(int x){
siz[x]=1;
for(int i=pre[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x]) continue;
fa[y]=x;
deep[y]=deep[x]+1;
dfs(y);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y]) son[x]=y;
}
}
int top[MAXN];
void DFS(int x,int topf){
insert(root[x],root[fa[x]],1,mx,a[x]);
top[x]=topf;
if(son[x]) DFS(son[x],topf);
for(int i=pre[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x]||y==son[x]) continue;
DFS(y,y);
}
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
return x;
}
signed main(){
n=read(),q=read(),typ=read();
for(int i=1;i<=n;++i) a[i]=read(),mx=max(mx,a[i]);
for(int i=1,u,v;i<n;++i){
u=read(),v=read();
add(u,v),add(v,u);
}
dfs(1);DFS(1,1);
while(q--){
int r=read(),k=read();
int lca;
for(int i=1;i<=k;++i){
p[i]=read();
p[i]=(p[i]-1+ans*typ)%n+1;
if(i==1) lca=p[i];
else lca=LCA(lca,p[i]);
}
ans=0x3f3f3f3f;
for(int i=1;i<=k;++i){
int pre=get_pre(root[fa[lca]],root[p[i]],1,mx,r);
int nxt=get_nxt(root[fa[lca]],root[p[i]],1,mx,r);
if(pre) ans=min(ans,abs(r-pre));
if(nxt) ans=min(ans,abs(nxt-r));
}
printf("%lld\n",ans);
}
return 0;
}
f:
不会了,打的暴力树状数组逆序对
标签:art print tin lca har operator 统计 get 主席树
原文地址:https://www.cnblogs.com/Juve/p/11655694.html