线段树
线段树合并
Luogu P4556
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MaxN=210000;
const int MaxS=110000;
template<typename Typename>
inline void Swap(Typename&x,Typename&y){
Typename t=x;x=y;y=t;
}
struct SegmentTree{
int Son[2][MaxN<<5],Data[MaxN<<5],Place[MaxN<<5],cnt;
SegmentTree(){cnt=0;memset(Son,0,sizeof(Son));}
inline void PushUp(int now){
if(Data[Son[0][now]]>=Data[Son[1][now]]){
Place[now]=Place[Son[0][now]];
Data[now]=Data[Son[0][now]];
}
else{
Place[now]=Place[Son[1][now]];
Data[now]=Data[Son[1][now]];
}
}
inline int Merge(int x,int y,int Left,int Right){
if(x==0||y==0)return x+y;
if(Left==Right){
Data[x]+=Data[y];
Place[x]=Left;
}
else{
register int mid=(Left+Right)>>1;
Son[0][x]=Merge(Son[0][x],Son[0][y],Left,mid);
Son[1][x]=Merge(Son[1][x],Son[1][y],mid+1,Right);
PushUp(x);
}
return x;
}
inline void Modify(int &now,int Left,int Right,int pos,int val){
if(now==0)now=++cnt;
if(Left==Right){
Place[now]=Left;
Data[now]+=val;
}
else{
register int mid=(Left+Right)>>1;
if(pos<=mid)Modify(Son[0][now],Left,mid,pos,val);
else Modify(Son[1][now],mid+1,Right,pos,val);
PushUp(now);
}
}
};SegmentTree Seg;
int To[MaxN*2],Next[MaxN*2],Last[MaxN],cnt;
inline void Insert(int from,int to){
To[cnt]=to;
Next[cnt]=Last[from];Last[from]=cnt++;
}
int Deep[MaxN],Dp[MaxN][31],Bit[31];
inline void Dfs(int from,int dad){
Deep[from]=Deep[dad]+1;
Dp[from][0]=dad;
for(register int i=1;i<=30;i++)
Dp[from][i]=Dp[Dp[from][i-1]][i-1];
for(register int k=Last[from];k!=-1;k=Next[k])
if(To[k]!=dad)Dfs(To[k],from);
}
inline int GetLca(int x,int y){
if(Deep[x]<Deep[y])Swap(x,y);
for(register int i=30;i>=0;i--)
if(Deep[Dp[x][i]]>=Deep[y])x=Dp[x][i];
if(x==y)return x;
for(register int i=30;i>=0;i--)
if(Dp[x][i]!=Dp[y][i])
x=Dp[x][i],y=Dp[y][i];
return Dp[x][0];
}
int Root[MaxN],Ans[MaxN];
inline void Solve(int from,int dad){
for(register int k=Last[from];k!=-1;k=Next[k]){
if(To[k]==dad)continue;Solve(To[k],from);
Root[from]=Seg.Merge(Root[from],Root[To[k]],1,MaxS);
}
Ans[from]=Seg.Place[Root[from]];
if(Seg.Data[Root[from]]==0)Ans[from]=0;
}
int n,m;
inline void Init(){
Bit[0]=1;
for(register int i=1;i<=n;i++)
Bit[i]=Bit[i-1]<<1;
}
inline void ReInit(){
cnt=0;
memset(Last,-1,sizeof(Last));
}
inline void Work(){
scanf("%d%d",&n,&m);
for(register int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
Insert(x,y);
Insert(y,x);
}
Dfs(1,0);
for(register int i=1,x,y,d;i<=m;i++){
scanf("%d%d%d",&x,&y,&d);
int lca=GetLca(x,y);
Seg.Modify(Root[lca],1,MaxS,d,-1);
if(Dp[lca][0])Seg.Modify(Root[Dp[lca][0]],1,MaxS,d,-1);
Seg.Modify(Root[x],1,MaxS,d,1);
Seg.Modify(Root[y],1,MaxS,d,1);
}
Solve(1,0);
for(register int i=1;i<=n;i++)
printf("%d\n",Ans[i]);
}
int Task;
int main(){
Task=1;Init();
for(register int Case=1;Case<=Task;Case++){
ReInit();
Work();
}
return 0;
}
主席树
寻找第
k
k
k 小
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
template<int MaxN>
struct SegmentTrees{
struct Nodes{
int Left,Right;
int Son[2];
int Data;
};Nodes Node[MaxN*30];
int cnt;
inline void Update(int&now,int pre,int left,int right,int pos){
now=++cnt;
Node[now].Data=Node[pre].Data+1;
Node[now].Son[0]=Node[pre].Son[0];
Node[now].Son[1]=Node[pre].Son[1];
if(left==right)return;
else{
int mid=(left+right)>>1;
if(pos<=mid)
Update(Node[now].Son[0],Node[pre].Son[0],left,mid,pos);
else Update(Node[now].Son[1],Node[pre].Son[1],mid+1,right,pos);
}
}
inline int Query(int x,int y,int left,int right,int rank){
int t=Node[Node[y].Son[0]].Data-Node[Node[x].Son[0]].Data;
if(left==right)return left;
else{
int mid=(left+right)>>1;
if(rank<=t)
return Query(Node[x].Son[0],Node[y].Son[0],left,mid,rank);
else return Query(Node[x].Son[1],Node[y].Son[1],mid+1,right,rank-t);
}
}
};
const int MaxN=1e5+1e4;
SegmentTrees<MaxN>T;
int Root[MaxN];
int Arr[MaxN],Copy[MaxN];
int n,m,len;
int main(){
n=Reader();m=Reader();
for(int i=1;i<=n;i++){
Arr[i]=Reader();
Copy[i]=Arr[i];
}
sort(Copy+1,Copy+n+1);
len=unique(Copy+1,Copy+n+1)-Copy-1;
for(int i=1;i<=n;i++)
Arr[i]=lower_bound(Copy+1,Copy+len+1,Arr[i])-Copy;
for(int i=1;i<=n;i++){
T.Update(Root[i],Root[i-1],1,len,Arr[i]);
}
for(int i=1,l,r,c;i<=m;i++){
l=Reader();r=Reader();c=Reader();
printf("%d\n",Copy[T.Query(Root[l-1],Root[r],1,len,c)]);
}
return 0;
}
单点修改寻找第
k
k
k 小
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MaxN=5e4+1e3;
int Son[2][MaxN*200],Arr[MaxN],limit;
int Data[MaxN*200],Address[MaxN*2],Root[MaxN],size,cnt,Tmp[2][20];
inline int LowBit(const int&x){
return x&(-x);
}
inline void Modify(int&now,int left,int right,int pos,int val){
if(!now)now=++cnt;
Data[now]+=val;
if(left==right)return;
else{
int mid=(left+right)>>1;
if(pos<=mid)Modify(Son[0][now],left,mid,pos,val);
else Modify(Son[1][now],mid+1,right,pos,val);
}
}
inline void Modify(int pos,int val){
int rank=lower_bound(Address+1,Address+size+1,Arr[pos])-Address;
for(int i=pos;i<=limit;i+=LowBit(i))Modify(Root[i],1,size,rank,val);
}
inline int Query(int left,int right,int rank){
if(left==right)return left;
int mid=(left+right)>>1,sum=0;
for(int i=1;i<=Tmp[1][0];i++)sum+=Data[Son[0][Tmp[1][i]]];
for(int i=1;i<=Tmp[0][0];i++)sum-=Data[Son[0][Tmp[0][i]]];
if(rank<=sum){
for(int i=1;i<=Tmp[1][0];i++)Tmp[1][i]=Son[0][Tmp[1][i]];
for(int i=1;i<=Tmp[0][0];i++)Tmp[0][i]=Son[0][Tmp[0][i]];
return Query(left,mid,rank);
}
else{
for(int i=1;i<=Tmp[1][0];i++)Tmp[1][i]=Son[1][Tmp[1][i]];
for(int i=1;i<=Tmp[0][0];i++)Tmp[0][i]=Son[1][Tmp[0][i]];
return Query(mid+1,right,rank-sum);
}
}
inline int Ask(int begin,int end,int rank){
Tmp[1][0]=Tmp[0][0]=0;
for(int i=end;i>=1;i-=LowBit(i))Tmp[1][++Tmp[1][0]]=Root[i];
for(int i=begin-1;i>=1;i-=LowBit(i))Tmp[0][++Tmp[0][0]]=Root[i];
return Query(1,size,rank);
}
struct Operations{
int l,r,k;
bool opt;
};Operations Qry[11000];
char St[10];
int n,m;
int main(){
scanf("%d%d",&n,&m);limit=n;
for(int i=1;i<=n;i++)
scanf("%d",&Arr[i]),Address[++size]=Arr[i];
for(int i=1;i<=m;i++){
scanf("%s",St+1);
Qry[i].opt=(St[1]=='Q');
if(Qry[i].opt){
scanf("%d%d%d",&Qry[i].l,&Qry[i].r,&Qry[i].k);
}
else{
scanf("%d%d",&Qry[i].l,&Qry[i].k);
Address[++size]=Qry[i].k;
}
}
sort(Address+1,Address+1+size);
size=unique(Address+1,Address+1+size)-Address-1;
for(int i=1;i<=n;i++)
Modify(i,1);
for(int i=1;i<=m;i++){
if(Qry[i].opt){
printf("%d\n",Address[Ask(Qry[i].l,Qry[i].r,Qry[i].k)]);
}
else{
Modify(Qry[i].l,-1);
Arr[Qry[i].l]=Qry[i].k;
Modify(Qry[i].l,1);
}
}
return 0;
}