【noip2013】
noip2013
转圈游戏
快速幂模板
ll qpow(ll a,ll b){
ll ret=1;
while(b){
if(b&1) ret=ret*a%n;
a=a*a%n,b>>=1;
}
return ret;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n),rd(m),rd(k),rd(x);
printf("%lld",(qpow(10ll,k)*m%n+x)%n);
return 0;
}
火柴排队
使\(\sum(a_i-b_i)^2\)最小
即排名相同的在同一个位置\(\sum(a_i-b_i)^2\)就最小
c[a[i].id]=b[i].id
得理解 \(c[i]\)中\(i\)对应\(a\)中第\(i\)小的数的位置,\(c[i]\)对应\(b\)中第\(i\)小的数的位置 排完序后\(c[i]=i\)即\(a\)中第\(i\)小的数的位置与中第\(i\)小的数的位置相同
再复习一下两种求逆序对的方法
struct node{int w,id;}a[N],b[N];
bool cmp(node x,node y){return x.w<y.w;}
int query(int x){int ret=0;while(x>0)ret=(ret+t[x])%P,x-=(x&(-x));return ret;}
void upd(int x){while(x<=n)++t[x],x+=(x&(-x));}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n);
for(int i=1;i<=n;++i) rd(a[i].w),a[i].id=i;
for(int i=1;i<=n;++i) rd(b[i].w),b[i].id=i;
sort(a+1,a+n+1,cmp),sort(b+1,b+n+1,cmp);
for(int i=1;i<=n;++i) c[a[i].id]=b[i].id;
for(int i=n;i;--i)
upd(c[i]),ans=(ans+query(c[i]-1))%P;
printf("%d",ans);
return 0;
}
struct node{int w,id;}a[N],b[N];
bool cmp(node x,node y){return x.w<y.w;}
void mergesort(int l,int r){
if(l>=r) return;
int mid=l+r>>1,pl=l,pr=mid+1,k=l;
mergesort(l,mid),mergesort(mid+1,r);
while(pl<=mid&&pr<=r)
if(c[pl]<=c[pr]) rk[k++]=c[pl++];
else rk[k++]=c[pr++],ans=(ans+mid-pl+1)%P;
while(pl<=mid) rk[k++]=c[pl++];
while(pr<=r) rk[k++]=c[pr++];
for(int i=l;i<=r;++i) c[i]=rk[i];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n);
for(int i=1;i<=n;++i) rd(a[i].w),a[i].id=i;
for(int i=1;i<=n;++i) rd(b[i].w),b[i].id=i;
sort(a+1,a+n+1,cmp),sort(b+1,b+n+1,cmp);
for(int i=1;i<=n;++i) c[a[i].id]=b[i].id;
mergesort(1,n);
printf("%d",ans);
return 0;
}
货车运输
先kruskal构一个最大生成树 然后lca倍增询问
犯了个sb错误 图有可能不连通而是有多个连通块
int tot,head[N];
struct edge{int v,w,nxt;}e[N<<1];
void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
struct node{int u,v,w;}a[M];
bool cmp(node x,node y){return x.w>y.w;}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void kruskal(){
for(int i=1;i<=n;++i) f[i]=i;
for(int i=1,cnt=0,u,v,w;i<=m;++i)
if(find(u=a[i].u)!=find(v=a[i].v)){
add(u,v,a[i].w),add(v,u,a[i].w);
f[f[u]]=f[v],++cnt;
if(cnt==n-1) return;
}
}
int dep[N],p[N][15],mn[N][15];
void dfs(int u,int ff){
for(int i=head[u],v;i;i=e[i].nxt)
if((v=e[i].v)!=ff) dep[v]=dep[u]+1,p[v][0]=u,mn[v][0]=e[i].w,dfs(v,u);
}
void doubling(){
for(int j=1;j<=14;++j)
for(int i=1;i<=n;++i)
if(dep[i]>=1<<j) p[i][j]=p[p[i][j-1]][j-1],mn[i][j]=Min(mn[p[i][j-1]][j-1],mn[i][j-1]);
}
int query(int x,int y){
int ret=inf;
if(dep[x]>dep[y]) swap(x,y);
for(int i=14;i>=0;--i)
if(dep[p[y][i]]>=dep[x]) ret=Min(ret,mn[y][i]),y=p[y][i];
if(x==y) return ret;
for(int i=14;i>=0;--i)
if(p[x][i]!=p[y][i]) ret=Min(ret,Min(mn[x][i],mn[y][i])),x=p[x][i],y=p[y][i];
return Min(ret,Min(mn[x][0],mn[y][0]));
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n),rd(m);
for(int i=1;i<=m;++i) rd(a[i].u),rd(a[i].v),rd(a[i].w);
sort(a+1,a+m+1,cmp),kruskal();
for(int i=1;i<=n;++i) if(!dep[i]) dep[i]=1,dfs(i,0);
doubling();rd(q);
for(int i=1,x,y;i<=q;++i){
rd(x),rd(y);
if(find(x)!=find(y)) puts("-1");
else printf("%d\n",query(x,y));
}
return 0;
}
积木大赛
把序列分成\((a_1,..a_i),(a_{i+1},...a_j)...(a_k,...a_n)\)多个非递减序列
然后所有段中最大值的和减去除第一段外的段的最小值,化简一下
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n);
for(int i=1;i<=n;++i) rd(a[i]);
for(int i=2,pre=a[1];i<=n;pre=a[i++])
if(a[i]>pre) ans+=a[i]-pre;
printf("%lld",ans+a[1]);
return 0;
}
花匠
求最长波动序列长度
对于当前花\(i\)它是波峰,若\(h_{i+1}<h_i\)则第\(i+1\)盆为波谷,若\(h_{i+1}\ge h_i\),则往下找高度小于\(h_{i+1}\)的花,相当于将花\(i\)移掉换为花\(i+1\),换为\(i+1\)结果一定不会比\(i\)差 花\(i\)为波谷同理
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n);
for(int i=1;i<=n;++i) rd(a[i]);
for(int i=2,pre=2;i<=n;++i)//0谷 1峰
if(a[i]<a[i-1]&&pre) ++ans,pre=0;
else if(a[i]>a[i-1]&&pre!=1) ++ans,pre=1;
printf("%d",ans+1);
return 0;
}
华容道
首先要将空格子移到起始格子那里 若空格子在某一棋子周围 那么就可以转为空格子从当前格子的某一方向移到另一个与其相反的方向上去 预处理
\(cost[i][j][k][l]\)表示当前位置\((i,j)\),空格在其方向\(k\)上,将空格移到方向\(l\)上且不经过\((i,j)\)的最小步数 对于每个点bfs预处理出来
每个询问前 先\(dfs\)将空格移动到起点处 然后最短路
突然发现我连2维数组内部怎么排的都不知道orz
int dis[N][N];
queue<pii>q;bool vis[N][N];
void bfs(int x,int y,int X,int Y){
memset(vis,0,sizeof(vis)),memset(dis,inf,sizeof(dis));
q.push(make_pair(x,y)),dis[x][y]=0,vis[x][y]=vis[X][Y]=1;
while(!q.empty()){
int nx=q.front().first,ny=q.front().second;q.pop();
for(int i=0,xx,yy;i<4;++i){
xx=nx+dx[i],yy=ny+dy[i];
if(xx<1||xx>n||yy<1||yy>m||!mp[xx][yy]||vis[xx][yy]) continue;
q.push(make_pair(xx,yy)),vis[xx][yy]=1,dis[xx][yy]=dis[nx][ny]+1;
}
}
}
struct node{int x,y,dir;};
int sdis[N][N][4];
queue<node>q2;bool svis[N][N][4];
int spfa(){
if(sx==tx&&sy==ty) return 0;
bfs(ex,ey,sx,sy);
memset(sdis,inf,sizeof(sdis));
for(int i=0,nx,ny;i<4;++i){
nx=sx+dx[i],ny=sy+dy[i];
if(nx<1||nx>n||ny<1||ny>m||!mp[nx][ny]||dis[nx][ny]>=inf) continue;
sdis[sx][sy][i]=dis[nx][ny],svis[sx][sy][i]=1,q2.push(node{sx,sy,i});
}
while(!q2.empty()){
int nx=q2.front().x,ny=q2.front().y,dir=q2.front().dir;
q2.pop();
for(int i=0,xx,yy,w;i<4;++i){
xx=nx+dx[i],yy=ny+dy[i];
if(xx<1||xx>n||yy<1||yy>m||!mp[xx][yy]) continue;
w=cost[nx][ny][dir][i]+sdis[nx][ny][dir]+1;
if(sdis[xx][yy][i^1]>w){
sdis[xx][yy][i^1]=w;
if(!svis[xx][yy][i^1]) svis[xx][yy][i^1]=1,q2.push(node{xx,yy,i^1});
}
}
svis[nx][ny][dir]=0;
}
int ret=inf;
for(int i=0;i<4;++i) ret=min(ret,sdis[tx][ty][i]);
if(ret>=inf) return -1;
else return ret;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
rd(n),rd(m),rd(Q);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) rd(mp[i][j]);
memset(cost,inf,sizeof(cost));
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(mp[i][j]) for(int k=0,x,y;k<4;++k){
x=i+dx[k],y=j+dy[k];
if(x<1||y<1||x>n||y>m||!mp[x][y]) continue;
bfs(x,y,i,j);
for(int l=0;l<4;++l){
int xx=i+dx[l],yy=j+dy[l];
cost[i][j][k][l]=dis[xx][yy];
}
}
while(Q--) rd(ex),rd(ey),rd(sx),rd(sy),rd(tx),rd(ty),printf("%d\n",spfa());
return 0;
}