zoukankan      html  css  js  c++  java
  • TopCoder Div2

    代码附在文末.

    多组数据一定要初始化啊啊啊
    贪心要[大胆]猜想,小心证明


    A

    题目翻译

    题目描述
    有两个正整数A和B,两个操作+3或者-2。
    问,至少多少次操作可以让A变到B

    输入
    多组数据,第一行一个整数T(1<=T<=5)
    两个整数A和B(1<=A,B<=100)

    输出
    最少操作次数

    样例输入

    3
    10 14
    23 23
    18 12
    

    样例输出

    3
    0
    3
    

    Solution

    多种做法, 是一道有趣的题.
    最方便的做法是 (A<B)(+3), (A>B)(-2), 贪心的合理性显然可证.
    至于我是类似的方法只是讨论了 A 和 B 的大小关系,手动算了一下.
    考试时候神奇地把 (A-B) 写成了 (B-A) emm.


    B

    题目翻译

    题目描述
    有一个N*M的迷宫,每个格子是空地或者障碍,现在从一个起点出发,共有2中操作。

    1. 沿着上、下、左、右4个方向走到相邻的空地上,时间是1
    2. 沿着上下左右4个方向,跨越障碍,跳到最近的空地上,时间是2
      问,从起点到终点最少的时间。如果不能到达输出-1

    输入
    多组数据,第一行一个整数T(1<=T<=10)
    第一行两个整数N和M(1<=N,M<=50),表示地图的大小
    接下来N行,每行M个字符,仅包含两种字符“.”和“#”,分别表示空地和障碍
    接下来4个整数r1、c1、r2、c2,表示起点和终点的行列。
    起点终点保证唯一,且都是空地。

    输出
    从起点到终点最少时间。

    样例输入

    2
    4 4
    .##.
    .###
    .###
    ....
    0 0 3 3
    2 2
    #.
    .#
    0 1 1 0
    

    样例输出

    4
    -1
    

    Solution

    SPFA/Dijkstra最短路直接跑啊,
    这种弱鸡题目我也会做我真是无话可说.
    注意多组数据的初始化处理.


    C

    题目翻译

    题目描述
    我们称一个序列A中的某一个数为重数,当且仅当该数在序列中出现的次数超过序列长度的一半。
    例如:序列{1,2,1}中,1就是重数。而在序列{1,2,3}和{1,2,1,3}中都不存在重数。
    现在给定一个包含n个元素的序列A,每个元素为整数,范围在[0,m-1]。你的任务是统计出包含重数的子区间共有多少个。
    由于出题人不想生成大文件。。。输入数据有3个整数构成,分别为n,seed和m。出题人告诉你用如下方法生成数据:

    for i = 0 .. n-1:
        A[i] = (seed div 2^16) modulo m
        seed = (seed * 1103515245 + 12345) modulo 2^31
    

    其中:div表示整除;^表示乘幂;modulo 表示取模

    输入
    三个整数n(1<=n<=10^5), seed(0<=seed<=2^31-1), m(1<=m<=50)

    输出
    输出生成的序列中,包含重数的子区间数量

    样例输入

    5
    200
    5
    
    
    10
    15
    3
    
    
    8
    12345678
    1
    

    样例输出

    8
    
    23
    
    36
    

    提示

    样例1解释
    A = {0, 0, 1, 2, 0},包含1个元素的子区间有5个
    剩下三个分别为{0, 0}、{0, 0, 1}、{0, 0, 1, 2, 0}.

    Solution

    这是一类典型的数列题; 不妨先考虑 (O(n^2)) 的做法;
    因为 m 较小, 不妨把每种元素值看做颜色.
    首先显然每个区间 最多只有 1 个重数, 我们可以分别考虑每种颜色对答案的贡献.
    对于每种颜色, 显然我们需要枚举 两端 后在 (O(1)) 时间复杂度内判断该区间是否有 "重数".
    可以用 前缀和 优化, 用 cnt[col][i] 表示前 i 个元素中颜色 col 出现的个数, 那么区间 [l,r] 中颜色 col 是重数的条件就是:

    [ cnt[col][r] - cnt[col][l-1] > frac {r - l + 1}{2} ]

    移项后得到:

    [ 2cnt[l-1]-l leq 2cnt[r] - r - 2 ]

    那么枚举右端点 (i) 后只要统计有多少个 (1 leq j < i) 满足 (2cnt[j-1] - j leq 2cnt[r] - r - 2) 即可, 这个操作可以中 树状数组/线段树(O(n log n)) 时间内求解.

    这道题还有另外一种做法: 对于每种颜色, 把该颜色的点的值赋为 1, 其它颜色点的值fuw赋为 -1, 那么问题就转化为了查找有多少区间内数字的和大于0, 前缀和操作枚举右端点也可以用树状数组维护.这种方法常数更小(因为维护值的范围是原来的2/3).

    我这个蒟蒻成功的又没有初始化树状数组...

    参考代码

    A

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    int A, B;
    const int cost1[3] = {0, 2, 4};
    const int cost2[2] = {0, 3};
    
    int main(){
    	int T; scanf("%d", &T);
    	while (T--){
    		scanf("%d%d", &A, &B);
    		if (A < B) printf("%d
    ", (B - A) / 3 + cost1[(B-A) % 3]);
    		else printf("%d
    ", (A - B) / 2 + cost2[(A-B) % 2]);
    	}
    	return 0;
    }
    

    B

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define pii pair<int,int>
    using namespace std;
     
    const int INF = 10000000;
    const int maxn = 55;
    int T, n, m, r1, c1, r2, c2;
    char mat[maxn][maxn];
    int edgenum, head[maxn * maxn], vet[200007], nxt[200007], val[200007];
    inline void addedge(int u, int v, int w){
        ++edgenum;
        vet[edgenum] = v;
        val[edgenum] = w;
        nxt[edgenum] = head[u];
        head[u] = edgenum;
    }
     
    inline int id(int x, int y){
        return x * m + y;
    }
     
    int up[maxn][maxn], left[maxn][maxn];
    inline void pre(){
        for (int i = 0; i < m; ++i)
            up[0][i] = (mat[0][i] == '.') ? 0 : INF;
        for (int i = 0; i < n; ++i)
            left[i][0] = (mat[i][0] == '.') ? 0 : INF;
         
        for (int i = 1; i < n; ++i)
            for (int j = 0; j < m; ++j)
                up[i][j] = (mat[i][j] == '.') ? 0 : (up[i-1][j] + 1);
        for (int i = 0; i < n; ++i)
            for (int j = 1; j < m; ++j)
                left[i][j] = (mat[i][j] == '.') ? 0 : (left[i][j-1] + 1);       
    }
     
    const int dx[4] = {1, 0, 0, -1};
    const int dy[4] = {0, 1, -1, 0};
    inline void build(){
        memset(head, 0, sizeof(head));
        edgenum = 0;
        for (int x = 0; x < n; ++x)
            for (int y = 0; y < m; ++y){
                if (mat[x][y] == '#') continue;
                for (int k = 0; k < 4; ++k){
                    int xx = x + dx[k], yy = y + dy[k];
                    if (xx >= 0 && xx < n && yy >= 0 && yy < m){
                        if (mat[xx][yy] == '.') addedge(id(x,y), id(xx,yy), 1);
                        else{
                            if (up[xx][yy] < INF){
                                addedge(id(x,y), id(x - up[xx][yy] - 1, y), 2);
                                addedge(id(x - up[xx][yy] - 1, y), id(x,y), 2);
                            }
                            if (left[xx][yy] < INF){
                                addedge(id(x, y), id(x, y - left[xx][yy] - 1), 2);
                                addedge(id(x, y - left[xx][yy] - 1), id(x, y), 2);
                            }
                        }
                    }
                }
            }
    }
     
    int dist[maxn * maxn]; bool vis[maxn * maxn];
    priority_queue< pii, vector< pii >, greater< pii > >Qmin;
    inline void Dijkstra(int s){
        for (int i = 0; i <= id(n, m); ++i){
            dist[i] = INF;
            vis[i] = false;     
        }
        dist[s] = 0; Qmin.push( make_pair(0, s) );
        for (int i = 0; i <= id(n, m); ++i){
            while (!Qmin.empty() && vis[Qmin.top().second]) Qmin.pop();
            if (Qmin.empty()) break;
            int u = Qmin.top().second; Qmin.pop();
            vis[u] = true;
            for (int e = head[u]; e; e = nxt[e]){
                int v = vet[e], w = val[e];
                if (dist[v] > dist[u] + w){
                    dist[v] = dist[u] + w;
                    Qmin.push(make_pair(dist[v], v));
                }
            }
        }
    }
     
    int main(){
        scanf("%d", &T);
        while (T--){
            scanf("%d%d", &n, &m);
            for (int i = 0; i < n; ++i)
                scanf("%s", mat[i]);
            scanf("%d%d%d%d", &r1, &c1, &r2, &c2);
            
            pre();
            build();
            Dijkstra(id(r1,c1));
             
            if (dist[id(r2,c2)] < INF) printf("%d
    ", dist[id(r2,c2)]);
            else printf("-1
    ");
        }
        return 0;
    }
    

    C

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
     
    const int maxn = 100007;
    const int delta = 100001;
    const int maxval = 300005;
    int a[maxn], cnt[maxn];
    int n, seed, m;
    ll Ans;
     
    int C[maxn * 3];
    inline int lowbit(int x){return x & (-x);}
    inline void add(int i, int x){
        i = i + delta;
        for (; i <= maxval; i += lowbit(i))
            C[i] += x;
    }
    inline int sum(int i){
        i = i + delta;
        if (i < 1) return 0;
        int res = 0;
        for (; i >= 1; i -= lowbit(i))
            res += C[i];
        return res;
    }
     
    int main(){
        scanf("%d%d%d", &n, &seed, &m);
        for (int i = 1; i <= n; ++i){
            a[i] = seed / (1 << 16) % m;
            seed = ((ll)seed * 1103515245 + 12345) % (1LL << 31);
            //printf("%d
    ", a[i]);
        }
         
        Ans = 0;
             
        for (int col = 0; col < m; ++col){
            memset(C, 0, sizeof(C));
             
            cnt[0] = 0;
            for (int i = 1; i <= n; ++i)
                cnt[i] = cnt[i-1] + (a[i] == col);
             
            add(-1, 1);
            for (int i = 1; i <= n; ++i){
                Ans += sum(cnt[i] * 2 - i - 2);
                //if (col <= 2)printf("%d %d
    ", col, sum(cnt[i] * 2 - i - 2));
                add(cnt[i]*2-i-1, 1);
            }
        }
         
        printf("%lld
    ", Ans);
        return 0;
    }
    
    
  • 相关阅读:
    PHP远程下载图片,微信头像存到本地,本地图片转base64
    jQuery Validate自定义错误信息,自定义方法
    创建自己的composer包
    js,JQ获取短信验证码倒计时
    JQ JS复制到剪贴板
    js,JQuery 生成二维码
    js,JQuery实现,带筛选,搜索的select
    HTML5拖放牛刀小试
    HTML5上传图片预览功能
    一次dropzone体验
  • 原文地址:https://www.cnblogs.com/YJZoier/p/9711572.html
Copyright © 2011-2022 走看看