2017-10-23离线赛总结

来源:互联网 发布:知乎怎么邀请提问 编辑:程序博客网 时间:2024/06/05 08:22

失分小结:
估分:300
实际分数:300
。。。一个半小时就打完了。。开始怀疑人生。。。
但幸好后来有检查,第三题有很多小bug,如果没看出来可能就要爆零了。。。
题解:
第一题
根据题意得
ans=(x+m10k)%n 可以看出这里面较难处理的就是10^k
将n移进来,得x%n+m10k%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;}