• NOIP2013 Day1


    1.转圈游戏

    https://www.luogu.org/problem/show?pid=1965

    这道题失误极大,把freopen注释掉了,导致第一题暴0.

    注意:在考试时一定要留下最后的时间检查格式!!!

    由于此题中k的值很大,所以暴力只能过80%数据,需要用到快速幂。

    #include <cstdio>
    long long n,m,k,x,ans,t;
    int main()
    {
        freopen("circle.in","r",stdin);
        freopen("circle.out","w",stdout); 
        scanf("%lld%lld%lld%lld",&n,&m,&k,&x);
        ans=1; t=10;
        while(k)
        {
            if(k%2==1)ans=(ans*t)%n;
            k/=2;
            t=((t%n)*(t%n))%n;
        }
        printf("%d",(x+(m*ans)%n)%n);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }

    2.火柴排队

    https://www.luogu.org/problem/show?pid=1966

    这道题可用树状数组||逆序对||归并排序完成

    献上树状数组代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct MyStruct
    {
        int data;
        int loc;
    }a[100010],b[100010];
    int e[100010], n, c[100010];
    int inline readint()
    {
        int x = 0;
        char c = getchar();
        while (c<'0' || c>'9') c = getchar();
        while (c >= '0'&&c <= '9')
        {
            x = x * 10 + c - '0';
            c = getchar();
        }
        return x;
    }
    int lowbit(int x)
    {
        return x&-x;//树状数组实现 
    }
    void add(int x,int t)
    {
        while (x <= n)
        {
            e[x] += t;
            e[x] %=99999997;
            x += lowbit(x);//每次往后加,可以改变后面对应的和 
        }
    }
    int sum(int x)
    {
        int s = 0;
        while(x)
        {
            s += e[x];
            s %= 99999997;
            x -= lowbit(x);//得到所求的和 
        }
        return s;
    }
    bool cmp(MyStruct x, MyStruct y)
    {
        return x.data < y.data;
    }
    int main()
    {
        n = readint();
        for (int i = 1; i <= n; i++)
        {
            a[i].data = readint();
            a[i].loc = i;//记录位置 
        }
        for (int i = 1; i <= n; i++)
        {
            b[i].data = readint();
            b[i].loc = 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].loc] = b[i].loc;//离散优化 
        }
        int ans = 0;
        for (int i = 1; i <= n; i++)
        {
            add(c[i], 1);//离散优化后大小就是正确顺序的位置 
            ans += i - sum(c[i]);//当前位置,减去之前比他大的数的个数  
            ans %= maxm;
        }
        printf("%d", ans);
        return 0;
    }

    3.货车运输

    本题用LCA+最大生成树完成。。。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define MAXN 10005
    using namespace std;
    int n,m;
    struct T
    {
        int v;
        int w;
        int next;
    }edge[100005];
     
    struct P
    {
        int u;
        int v;
        int w;
    }a[MAXN*5];
    bool cmp(P x,P y)
    {
        return x.w > y.w;
    }
     
    int head[MAXN],cnt;
    int f[MAXN];
    int find(int x)//并查集,判断是否在同一个集合内
    {
        if(f[x] == x) return f[x];
        else return f[x] = find(f[x]);
    }
    void Add_edge(int u,int v,int w)//树连边
    {
        edge[cnt].v = v;
        edge[cnt].w = w;
        edge[cnt].next = head[u];
        head[u] = cnt++;
    }
    void Union(int u,int v)//联通块
    {
        int x = find(u);
        int y = find(v);
        if(x != y) f[x] = y;
    }
    void kruskal()//最大生成树
    {
        for(int i = 0; i <= MAXN; i++)
            f[i] = i;
        for(int i = 1; i <= m; i++)
        {
            int u = a[i].u,v = a[i].v;
            if(find(u) != find(v))
            {
                Union(u,v);
                Add_edge(u,v,a[i].w);
                Add_edge(v,u,a[i].w);
            }
        }
    }
     
    int up[MAXN][25],g[MAXN][25],h[MAXN];//up[i][j]表示i的第2^j个祖先,g[i][j]表示i到i的第2^j个祖先路径上的最小权值,h[i]表示i在树中深度
    bool vis[MAXN];
    void build_tree(int u)
    {
        vis[u] = 1;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].v;
            if(!vis[v])
            {
                g[v][0] = edge[i].w; 
                up[v][0] = u;
                h[v] = h[u]+1;
                build_tree(v);
            }
        }
    }
    //把较深的一个点往上提,并记录他到祖先边权最小值,用他的一个祖先代替他
    int move(int &u,int H)
    {
        int res = 123546789;
        for(int i =20; i >= 0; i--)
        {
            if(h[up[u][i]] >= H)
            {
                res = min(res,g[u][i]);
                u = up[u][i];
            }
        }
        return res;
    }
    int query(int u,int v)//自认为是最难的地方
    {
        if(find(u) != find(v)) return -1;
        int res = 123456789;
        if(h[u] != h[v]) res = h[u] > h[v]?move(u,h[v]):move(v,h[u]);
        if(u == v) return res;
        for(int i = 20; i >= 0; i--)//倍增的同时记录最小值,两个点越来越逼近公共祖先
        {
            if(up[u][i] != up[v][i])
            {
                res = min(res,min(g[u][i],g[v][i]));
                u = up[u][i];
                v = up[v][i];
            }
        }
        res = min(res,min(g[u][0],g[v][0]));//实际上到了这一步up[x][0] == up[y][0]因为它们的已经在同一棵子树里面
        //printf("up[u][0]: %d
    ",up[u][0]);
        //printf("up[v][0]: %d
    ",up[v][0]);
        return res;
    }
     
    int main()
    {
        memset(head,-1,sizeof head);
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= m; i++)
            scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
        sort(a+1,a+m+1,cmp);
        kruskal();
         
        for(int i = 1; i <= n; i++)//构建森林,并且初始化h,up,g
        {
            if(!vis[i])
            {
                h[i] = 0;
                build_tree(i);
                g[i][0] = 123456789;
                up[i][0] = i;
            }
        }
        for(int i = 1; i <= 20; i++)//预处理up和g,i大了也没有什么影响
        {
            for(int j = 1; j <= n; j++)
            {
                up[j][i] = up[up[j][i-1]][i-1];
                g[j][i] = min(g[j][i-1],g[up[j][i-1]][i-1]);
            }
        }
         
        int q;
        scanf("%d",&q);
        for(int i = 1; i <= q; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",query(x,y));
        }
        return 0;
    }
  • 相关阅读:
    Tomcat启动过程[更详细]
    数据库连接池原理
    Druid
    Spring的注解积累
    React基础知识
    mac里git项目删除.DS_Store文件
    GET请求参数为中文时乱码分析
    npm中package.json详解
    前后端分离工具之ftl-server
    利用performance属性查看网页性能
  • 原文地址:https://www.cnblogs.com/wisdom-jie/p/7738164.html
Copyright © 2020-2023  润新知