失分小结:
估分:300
实际分数:300
。。。一个半小时就打完了。。开始怀疑人生。。。
但幸好后来有检查,第三题有很多小bug,如果没看出来可能就要爆零了。。。
题解:
第一题
根据题意得
ans=
(x+m∗10k)%n
可以看出这里面较难处理的就是10^k
将n移进来,得
x%n+m∗10k%m
10k%n
就可以用快速幂解决了
第二题
看一下这题的数据就知道不是个dp题,
根据一些交换性质,可以知道A交换或是B交换是一样的
那么就保持A不动,使B与A对应
相信做过筷子那道题的人都知道没做过也知道啊
把大小一一对应才是最优的
那后就离散化,像之前做过的一些题目一样模拟过来就好了
显然要一些数据结构或归并
代码实现
void update(int x,int a){
while(x<=n){
Sum[x]+=a;
x+=x&-x;
}
}
int query(int x){
int res=0;
while(x){
res+=Sum[x];
x-=x&-x;
}
return res;
}
void solve(){
memset(Sum,0,sizeof(Sum));
FOR(i,1,n)C[i]=A[i],D[i]=B[i];
sort(C+1,C+n+1);
sort(D+1,D+n+1);
FOR(i,1,n){
A[i]=lower_bound(C+1,C+n+1,A[i])-C;
B[i]=lower_bound(D+1,D+n+1,B[i])-D;
}
FOR(i,1,n)W[B[i]]=i;
ll ans=0;
DOR(i,n,1){
int k=query(W[A[i]]);
ans+=k;
update(W[A[i]],1);
}
printf("%lld\n",ans%P);
}
int main(){
scanf("%d",&n);
FOR(i,1,n)scanf("%d",&A[i]);
FOR(i,1,n)scanf("%d",&B[i]);
solve();
return 0;
}
第三题
首先看到这道题,就能想到最优化。比如说有重边,那么就一定要取最优的
题目关心的是路径上的最小值,那么就要尽量使最小值最大化。
最后会发现,所有点之间的最优路径是统一的,
即在最优的情况下,所有点之间的路径刚好可以构成一棵树。
然而这棵树应该是一颗类最大生成树(边权最大,而不是边权和最大)。
但实现是一模一样的。
然后对于每个询问,就是倍增求lca,同时求一下最小边权就好了
都是套路
代码实现
#include<bits/stdc++.h>
using namespace std;
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define ll long long
#define du double
#define pb push_back
#define M 50005
#define N 10005
#define S 18
//mod long long 乘法 文件名 调试
inline void chk_mi(int &x,int y){if(x>y)x=y;}
struct Node{int x,y,v;}E[M];
struct node{int x,v;};
vector<node>edge[N];
bool cmp(Node a,Node b){return a.v>b.v;}
int Fa[S][N],dis[S][N],dep[N],fa[N];
bool mark[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void dfs(int x,int f){
Fa[0][x]=f;
dep[x]=dep[f]+1;
for(int i=0;i<(int)edge[x].size();i++){
int y=edge[x][i].x;
if(y==f)continue;
dis[0][y]=edge[x][i].v;
dfs(y,x);
}
}
int LCA(int x,int y){
if(dep[x]>dep[y])swap(x,y);
int len=dep[y]-dep[x],res=1e8;
FOR(i,0,S-1){
if(len&(1<<i)){
chk_mi(res,dis[i][y]);
y=Fa[i][y];
}
}
if(x==y)return res;
DOR(i,S-1,0){
if(Fa[i][x]!=Fa[i][y]){
chk_mi(res,dis[i][x]);
chk_mi(res,dis[i][y]);
x=Fa[i][x];
y=Fa[i][y];
}
}
chk_mi(res,dis[0][x]);
chk_mi(res,dis[0][y]);
return res;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
FOR(i,1,m)scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].v);
//mlogm
sort(E+1,E+m+1,cmp);
FOR(i,1,n)fa[i]=i;
FOR(i,1,m){
int x=E[i].x,y=E[i].y,v=E[i].v;
int a=find(x),b=find(y);
if(a!=b){
edge[x].pb((node){y,v});
edge[y].pb((node){x,v});
fa[a]=b;
mark[x]=1,mark[y]=1;//在树里
}
}
FOR(i,1,n)if(mark[i]){dfs(i,0);break;}
//s*n
FOR(i,1,S-1)FOR(j,1,n){
Fa[i][j]=Fa[i-1][Fa[i-1][j]];
dis[i][j]=dis[i-1][Fa[i-1][j]];
chk_mi(dis[i][j],dis[i-1][j]);
}
int q;
scanf("%d",&q);
//qlogn
FOR(i,1,q){
int x,y;
scanf("%d%d",&x,&y);
if(!mark[x]||!mark[y]){puts("-1");continue;}
printf("%d\n",LCA(x,y));
}
return 0;
}