杂数据结构选做
杂数据结构选做
持续更新ing...
更新多少取决于我卷了多少
似乎都是比较基础的东西,但是我数据结构太菜了,没办法
╮(╯_╰)╭
#9016. CodeChef MINXORSEG
有两种做法,我敲的后一种
第一种
先不考虑范围问题,考虑现在有三个点
根据这点,我们考虑建
但是显然不能暴力的找所有点对,所以把挂着的点按编号排序后,相邻两点组成一个点对即可,这样显然最优
那么我们现在就有
再来考虑范围限制
第二种
这种应该要比上一种好写一些,但是其实都挺好写的
其实两种做法差不多?
还是根据第一种中提到的,考虑
考虑直接贪心的对每个点
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,q,a[N],p[N];
int b,to[N][30];
bool cmp(int x,int y){
if((a[x]>>b)==(a[y]>>b)) return x<y;
return (a[x]>>b)<(a[y]>>b);
}
struct node{
int l,r,id;
bool operator < (const node &other)const{
return r<other.r;
}
}cn[N];
int c[N],ans[N];
void add(int x,int y){ for(x=n-x+1;x<=n;x+=x&-x) c[x]=min(c[x],y); }
int ask(int x){
int ans=1e9;
for(x=n-x+1;x;x-=x&-x) ans=min(ans,c[x]);
return ans;
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),p[i]=i,c[i]=1e9;
for(b=0;b<30;++b){
stable_sort(p+1,p+n+1,cmp);
for(int i=2;i<=n;++i) if((a[p[i]]>>b)==(a[p[i-1]])>>b) to[p[i]][b]=p[i-1];
}
for(int i=1;i<=q;++i) scanf("%d%d",&cn[i].l,&cn[i].r),cn[i].id=i;
sort(cn+1,cn+q+1);
for(int i=1,k=1;i<=n;++i){
for(int j=0;j<30;++j) if(to[i][j]) add(to[i][j],a[i]^a[to[i][j]]);
while(k<=q&&cn[k].r==i) ans[cn[k].id]=ask(cn[k].l),++k;
}
for(int i=1;i<=q;++i) printf("%d\n",ans[i]);
return 0;
}
P8078 [WC2022] 秃子酋长
从
的 区偷的 如果在分治结构上很难快速合并某些信息,我们就可以利用分块来做所以如果在分治结构上很难快速合并某些信息,我们就可以利用分块来做。反过来,我们如果想要用任何的分治结构做这道题,我们都需要发现一个性质,支持某种程度上比暴力更快地合并区间信息的性质。
考虑如果我们知道了
将
若
若
对于
当
那么就可以猫树分治
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+5;
int n,m,a[N],p[N];
struct node{ int l,r,id; };
bool cmp1(node a,node b){ return a.l<b.l; }
bool cmp2(node a,node b){ return a.r>b.r; }
ll ans[N];
vector<node> cn;
ll suf[N],pre[N],c[N];
queue<int> op;
void add(int x,int y){ if(abs(x)>N) return ; (x<0)&&(x+=n+1),op.push(x); for(;x<=n;x+=x&-x) c[x]+=y; }
ll ask(int x){
ll ans=0;
for((x<0)&&(x+=n+1);x;x-=x&-x) ans+=c[x];
return ans;
}
void clear(){
while(!op.empty()){
int x=op.front(); op.pop();
for(;x<=n;x+=x&-x) c[x]=0;
}
}
int le[N],ri[N],pos[N],A,B;
void work(int tl,int tr,int &A,int k){
for(int x=tl,y=tr;x;x=ri[x]){
while(y&&a[y]<a[x]) (x==tl)&&(A=min(A,k*y)),y=ri[y];
while(y&&a[x]<a[y]&&(!ri[x]||a[y]<a[ri[x]])) pos[x]=min(pos[x],k*y),y=ri[y];
}
}
void Val(int now,int &A,int k,int k1=1,bool flag1=1,bool flag2=1){
if(flag1){
if(le[now]) add(-k*pos[le[now]],2*k*k1*abs(max(-k*le[now],-k*now))); else add(-k*A,k*k1*now);
}
if(flag2){
if(ri[now]) add(-k*pos[now],2*k*k1*abs(max(-k*ri[now],-k*now))); else add(-k*pos[now],k*k1*now);
}
}
void work1(int now,int &A,int k){
Val(now,A,k,-1);
if(le[now]) ri[le[now]]=ri[now],(pos[le[now]]==1e9)?(pos[le[now]]=pos[now]):((pos[now]!=1e9)&&(pos[le[now]]=abs(min(-k*pos[le[now]],-k*pos[now])))); else (A==1e9)?(A=pos[now]):((pos[now]!=1e9)&&(A=abs(min(-k*A,-k*pos[now]))));
if(ri[now]) le[ri[now]]=le[now];
if(le[now]) Val(le[now],A,k,1,0,1);
else if(ri[now]) Val(ri[now],A,k,1,1,0);
}
void solve(int l,int r,vector<node> que,bool flag){
if(l==r) return ;
int mid=l+r>>1; vector<node> q1,q2,q3;
for(auto x:que){
if(x.r<=mid) q1.push_back(x);
else if(x.l>mid) q2.push_back(x);
else q3.push_back(x);
}
solve(l,mid,q1,0),solve(mid+1,r,q2,1);
for(auto x:q3) ans[x.id]=suf[x.l]+pre[x.r];
set<int> s; A=B=1e9;
for(int i=mid;i>=l;--i) s.insert(a[i]),pos[i]=1e9,le[i]=ri[i]=0;
int las=0,stl=0,str=0; for(auto x:s) le[p[x]]=p[las],(las)&&(ri[p[las]]=p[x]),las=x,(!stl)&&(stl=p[x]);
s.clear(); for(int i=mid+1;i<=r;++i) s.insert(a[i]),pos[i]=1e9,le[i]=ri[i]=0;
las=0; for(auto x:s) le[p[x]]=p[las],(las)&&(ri[p[las]]=p[x]),las=x,(!str)&&(str=p[x]);
work(stl,str,A,1),work(str,stl,B,-1),sort(q3.begin(),q3.end(),cmp1);
if(B<0) B=-B;
for(int i=mid+1;i<=r;++i) if(pos[i]<0) pos[i]=-pos[i];
clear(),add(A,-stl);
for(int now=l;now<=mid;++now){
if(ri[now]) add(pos[now],-2*max(ri[now],now)); else add(pos[now],-now);
}
for(int now=l,i=0;now<=mid;++now){
for(;i<q3.size()&&q3[i].l==now;++i) ans[q3[i].id]+=ask(q3[i].r);
work1(now,A,-1);
}
sort(q3.begin(),q3.end(),cmp2),clear();
add(-B,str);
for(int now=mid+1;now<=r;++now){
if(ri[now]) add(-pos[now],2*min(ri[now],now)); else add(-pos[now],now);
}
for(int now=r,i=0;now>mid;--now){
for(;i<q3.size()&&q3[i].r==now;++i) ans[q3[i].id]+=ask(-q3[i].l);
work1(now,B,1);
}
if(!flag){//suf
set<int> s;
for(int i=r;i>=l;--i){
suf[i]=i==r?0:suf[i+1];
auto it=s.lower_bound(a[i]);
if(it!=s.end()){
if(it!=s.begin()) suf[i]-=abs(p[*it]-p[*prev(it)]);
suf[i]+=p[*it]-i;
}
if(it!=s.begin()) suf[i]+=p[*prev(it)]-i;
s.insert(a[i]);
}
}else{//pre
set<int> s;
for(int i=l;i<=r;++i){
pre[i]=i==l?0:pre[i-1];
auto it=s.lower_bound(a[i]);
if(it!=s.end()){
if(it!=s.begin()) pre[i]-=abs(p[*it]-p[*prev(it)]);
pre[i]+=i-p[*it];
}
if(it!=s.begin()) pre[i]+=i-p[*prev(it)];
s.insert(a[i]);
}
}
}
int main(){
scanf("%d%d",&n,&m),cn.resize(m);
for(int i=1;i<=n;++i) scanf("%d",&a[i]),p[a[i]]=i;
for(int i=0;i<m;++i) scanf("%d%d",&cn[i].l,&cn[i].r),cn[i].id=i+1;
solve(1,n,cn,0);
for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)