原地爆炸
(1)区间
n2 预处理大暴力
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 8888
int tot,nxt[stan],first[stan],goal[stan];
int n,q,a[stan];
map<int,int>id;
int f1[stan],f2[stan],f[stan],sze[stan<<1],vis[stan<<1],lef,cnt,cnt1,cnt2,cnt3;
int ans[stan][stan],spi[stan];
int tota,pos1,pos2,x,y,now;
void addedge(int a,int b){
nxt[++tot]=first[a];first[a]=tot;goal[tot]=b;
return ;
}
signed main(){
n=read();q=read();
for(register int i=1;i<=n;++i){
a[i]=read();
if(!id[a[i]])
id[a[i]]=++cnt;
a[i]=id[a[i]];
}
for(register int i=n;i;--i)
addedge(a[i],i);
for(register int i=1;i<=cnt;++i)
for(register int j=i+1;j<=cnt;++j){
++tota;
cnt1=0;cnt2=0;cnt3=0;
for(int p=first[i];p;p=nxt[p])
f1[++cnt1]=goal[p];
for(int p=first[j];p;p=nxt[p])
f2[++cnt2]=goal[p];
cnt3=cnt1+cnt2;
pos1=1;pos2=1;
for(int k=1;k<=cnt3;++k){
if(pos2>cnt2||(pos1<=cnt1&&f1[pos1]else
f[k]=f2[pos2++];
}
now=8000;
vis[now]=tota;
sze[now]=f[1];
ans[i][j]=f[1]*(f[1]-1)/2;
f[cnt3+1]=n+1;
for(int k=1;k<=cnt3;++k){
if(a[f[k]]==i) ++now;
else --now;
if(vis[now]0;
vis[now]=tota;
}
ans[i][j]=ans[i][j]+(f[k+1]-f[k])*sze[now]+(f[k+1]-f[k])*(f[k+1]-f[k]-1)/2;
sze[now]=sze[now]+f[k+1]-f[k];
}
ans[j][i]=ans[i][j];
}
for(register int i=1;i<=cnt;++i){
spi[i]=0;
lef=0;
for(register int p=first[i];p;p=nxt[p]){
spi[i]=spi[i]+(goal[p]-lef)*(goal[p]-lef-1)/2;
lef=goal[p];
}
spi[i]=spi[i]+(n-lef)*(n-lef+1)/2;
}
for(register int i=1;i<=q;++i){
x=read();y=read();
x=id[x];y=id[y];
if((!x&&!y)||(x==y))
write((n+1)*n/2),puts("");
else if(!x||!y)
write(spi[x^y]),puts("");
else
write(ans[x][y]),puts("");
}
return 0;
}
(2)排列
线段树求最小值
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 111111
int n,num[stan],a[stan],sum[stan],pos[stan<<2],mini[stan<<3],tag[stan<<3];
void build(int k,int l,int r){
if(l==r){
mini[k]=l-a[l];
pos[k]=l;
return ;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
mini[k]=min(mini[k<<1],mini[k<<1|1]);
if(mini[k]==mini[k<<1|1])
pos[k]=pos[k<<1|1];
else
pos[k]=pos[k<<1];
return ;
}
void addtag(int k,int l,int r,int x,int y){
tag[k<<1]+=tag[k];mini[k<<1]-=tag[k];
tag[k<<1|1]+=tag[k];mini[k<<1|1]-=tag[k];
tag[k]=0;
if(x<=l&&r<=y){
--mini[k];
++tag[k];
return ;
}
int mid=l+r>>1;
if(x<=mid) addtag(k<<1,l,mid,x,y);
if(y>mid) addtag(k<<1|1,mid+1,r,x,y);
mini[k]=min(mini[k<<1],mini[k<<1|1]);
if(mini[k]==mini[k<<1|1])
pos[k]=pos[k<<1|1];
else
pos[k]=pos[k<<1];
return ;
}
void change(int k,int l,int r,int x,int d){
tag[k<<1]+=tag[k];mini[k<<1]-=tag[k];
tag[k<<1|1]+=tag[k];mini[k<<1|1]-=tag[k];
tag[k]=0;
if(l==r){
mini[k]=d;
return ;
}
int mid=l+r>>1;
if(x<=mid) change(k<<1,l,mid,x,d);
else change(k<<1|1,mid+1,r,x,d);
mini[k]=min(mini[k<<1],mini[k<<1|1]);
if(mini[k]==mini[k<<1|1])
pos[k]=pos[k<<1|1];
else
pos[k]=pos[k<<1];
return ;
}
signed main(){
n=read();
for(int i=1;i<=n;++i)
sum[i]=read();
for(int i=1;i<=n;++i)
a[i]=sum[i]-sum[i-1];
if(n<=1000){
for(int i=1;i<=n;++i)
for(int j=n;j;--j)
if(a[j]==j-1){
num[j]=i;
for(int k=j;k<=n;++k)
++a[k];
break;
}
}else{
build(1,1,n);
for(int i=1;i<=n;++i){
int x=pos[1];
num[x]=i;
change(1,1,n,x,n+2);
if(x1,1,n,x+1,n);
}
}
for(int i=1;i<=n;++i){
write(num[i]);putchar(' ');
}
return 0;
}
(3)边的处理
分治处理DP中点
复杂度?
O(mlogmn2+nq)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 22222
#define sten 222222
#define stin 33
struct edg{
int x,y,r,c;
}edge[stan];
struct query{
int x,y,l,r,id;
}que[sten],temp[sten];
int lef[stan][stin][stin],righ[stan][stin][stin],ans[sten],tmp,posl,posr;
int n,m,q;
void solve(int le,int re,int lq,int rq){
if(lq>rq) return;
if(le==re){
for(int i=lq;i<=rq;++i){
if(que[i].x!=que[i].y){
if(que[i].x==edge[le].x&&que[i].y==edge[le].y)
ans[que[i].id]=edge[le].c;
else
ans[que[i].id]=-1;
}else{
ans[que[i].id]=999999999;
if(que[i].x==edge[le].x&&que[i].y==edge[le].y)
ans[que[i].id]=edge[le].c;
ans[que[i].id]=min(ans[que[i].id],edge[le].r);
}
}
return ;
}else{
int mid=le+re>>1;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
lef[mid+1][i][j]=999999999;
righ[mid][i][j]=999999999;
}
lef[mid+1][i][i]=0;
righ[mid][i][i]=0;
}
for(int i=mid;i>=le;--i){
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
lef[i][j][k]=lef[i+1][j][k]+edge[i].r;
for(int j=1;j<=n;++j){
if(lef[i+1][j][edge[i].x]<999999999)
lef[i][j][edge[i].y]=min(lef[i][j][edge[i].y],lef[i+1][j][edge[i].x]+edge[i].c);
if(lef[i+1][j][edge[i].y]<999999999)
lef[i][j][edge[i].x]=min(lef[i][j][edge[i].x],lef[i+1][j][edge[i].y]+edge[i].c);
}
}
for(int i=mid+1;i<=re;++i){
for(int j=1;j<=n;++j)
for(int k=1;k<=n;++k)
righ[i][j][k]=righ[i-1][j][k]+edge[i].r;
for(int j=1;j<=n;++j){
if(righ[i-1][j][edge[i].x]<999999999)
righ[i][j][edge[i].y]=min(righ[i][j][edge[i].y],righ[i-1][j][edge[i].x]+edge[i].c);
if(righ[i-1][j][edge[i].y]<999999999)
righ[i][j][edge[i].x]=min(righ[i][j][edge[i].x],righ[i-1][j][edge[i].y]+edge[i].c);
}
}
for(int i=lq;i<=rq;++i)
if(que[i].l<=mid&&que[i].r>mid){
tmp=999999999;
for(int j=1;j<=n;++j)
tmp=min(tmp,lef[que[i].l][j][que[i].x]+righ[que[i].r][j][que[i].y]);
if(tmp>=999999999)
ans[que[i].id]=-1;
else
ans[que[i].id]=tmp;
}
for(int i=lq;i<=rq;++i)
temp[i]=que[i];
int posl=lq,posr=rq;
for(int i=lq;i<=rq;++i){
if(temp[i].r<=mid) que[posl++]=temp[i];
if(temp[i].l>mid) que[posr--]=temp[i];
}
solve(le,mid,lq,posl-1);
solve(mid+1,re,posr+1,rq);
}
return ;
}
signed main(){
n=read();m=read();q=read();
for(int i=1;i<=m;++i){
edge[i].x=read();
edge[i].y=read();
edge[i].c=read();
edge[i].r=read();
}
for(int i=1;i<=q;++i){
que[i].x=read();
que[i].y=read();
que[i].l=read();
que[i].r=read();
que[i].id=i;
}
solve(1,m,1,q);
for(int i=1;i<=q;++i){
write(ans[i]);
puts("");
}
}