P9550
这是一篇不用二维线段树的题解。
题意:
对于一个点
45 pts:
考虑暴力转移,
100 pts:
考虑题意,对于横坐标为
注:写横纵坐标时不要写反。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+10;
int l1[N],l2[N],r1[N],r2[N],a[N][N],k[N],dis[N][N];
struct a1{int minn;}x[N][N<<2];
void X(int i,int l,int r,int p,int a,int dis){
if(l==r){
x[a][p].minn+=dis;
return ;
}
int mid=(l+r)>>1;
if(mid>=i)X(i,l,mid,p<<1,a,dis);
else X(i,mid+1,r,p<<1|1,a,dis);
x[a][p].minn=min(x[a][p<<1].minn,x[a][p<<1|1].minn);
}
int G(int L,int R,int l,int r,int p,int a){
if(l>=L&&r<=R)return x[a][p].minn;
int mid=(l+r)>>1;
int ans=1e16;
if(mid>=L)ans=G(L,R,l,mid,p<<1,a);
if(mid<R) ans=min(ans,G(L,R,mid+1,r,p<<1|1,a));
return ans;
}
signed main(){
int n;
cin>>n;
for(int q=1;q<=n;q++){cin>>l1[q];if(l1[q]==0)l1[q]++;}
for(int q=1;q<=n;q++){cin>>r1[q];}
for(int q=1;q<=n;q++){cin>>l2[q];if(l2[q]==0)l2[q]++;}
for(int q=1;q<=n;q++){cin>>r2[q];}
for(int q=1;q<=n;q++)cin>>k[q];
for(int q=1;q<=n;q++){
for(int w=1;w<=n;w++){
a[q][w]=k[q]+k[w]-q-w;
X(q,1,n,1,w,a[q][w]);
}
}
for(int q=2;q<=n;q++)X(1,1,n,1,q,1e10);
for(int w=2;w<=n;w++){
for(int i=1;i<=n;i++){
X(i,1,n,1,n+1,G(l1[w],r1[w],1,n,1,i));
}
for(int i=1;i<=n;i++){
if(r2[i]!=0)X(w,1,n,1,i,G(l2[i],r2[i],1,n,1,n+1));
else X(w,1,n,1,i,1e10);
X(w,1,n,1,i,a[w][i]);
}
for(int i=1;i<=n;i++){
X(i,1,n,1,n+1,-G(l1[w],r1[w],1,n,1,i));
}
}
for(int q=1;q<=n;q++){
for(int w=1;w<=n;w++){
int o=G(q,q,1,n,1,w)-a[q][w];
if(o>=1e9)cout<<"inf ";
else cout<<o<<" ";
}
cout<<"\n";
}
return 0;
}