zoukankan      html  css  js  c++  java
  • Bestcoder Round#45

    1001

    给定数n,要我们求该数的二进制中有多少组1, 相邻的1称为1组, 直接位运算摸你即可

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <queue>
     7 #include <stack>
     8 #include <vector>
     9 #include <map>
    10 #include <set>
    11 #include <string>
    12 #include <math.h>
    13 using namespace std;
    14 #pragma warning(disable:4996)
    15 typedef long long LL;                   
    16 const int INF = 1<<30;
    17 /*
    18 
    19 */
    20 
    21 int main()
    22 {
    23     int t;
    24     LL n;
    25     scanf("%d", &t);
    26     while (t--)
    27     {
    28         scanf("%I64d", &n);
    29         int ans = 0;
    30         bool flag = true;
    31         while (n)
    32         {
    33             if ((n & 1))
    34             {
    35                 if (flag)
    36                 {
    37                     ans++;
    38                     flag = false;
    39                 }
    40             }
    41             else
    42                 flag = true;
    43 
    44             n >>= 1;
    45         }
    46         printf("%d
    ", ans);
    47     }
    48     return 0;
    49 }
    View Code

    1002

    比赛的时候,一直认为求逆序对,要用树状数组做, 就YY出了一个树状数组的解法。

    我把询问按照L从小到大排序,然后分为两种情况

    对于第一种情况,我们只要将左边的数从树状数组中减去,然后加上右边的数即可。

    对于第二种情况,我们将数状数组情况, 重新建树状数组

    其实比赛完之后,仔细想想,如果存在很多第二种情况(应该最多只有1000种,因为N<=1000) , 那么时间复杂度是N*N*logN, 应该是勉强可以过, 或者直接TLE

    不过自己YY出来这种想法, 还是挺好的。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <algorithm>
      5 #include <iostream>
      6 #include <queue>
      7 #include <stack>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 #include <string>
     12 #include <math.h>
     13 using namespace std;
     14 #pragma warning(disable:4996)
     15 typedef long long LL;                   
     16 const int INF = 1<<30;
     17 /*
     18 
     19 */
     20 struct Node
     21 {
     22     int l, r;
     23     int id;
     24     bool operator<(const Node &rhs)const
     25     {
     26         if (l == rhs.l)
     27             return r < rhs.r;
     28         return l < rhs.l;
     29     }
     30 }Q[100000+10];
     31 int a[1000 + 10];
     32 int b[1000 + 10];
     33 map<int, int> mark;
     34 int ans[100000 + 10];
     35 int sum[1000 + 10];
     36 int lowbit(int x)
     37 {
     38     return x & (-x);
     39 }
     40 void modify(int pos, int val, int n)
     41 {
     42     while (pos <= n)
     43     {
     44         sum[pos] += val;
     45         pos += lowbit(pos);
     46     }
     47 }
     48 int getSum(int pos)
     49 {
     50     int ret = 0;
     51     while (pos > 0)
     52     {
     53         ret += sum[pos];
     54         pos -= lowbit(pos);
     55     }
     56     return ret;
     57 }
     58 int main()
     59 {
     60     int n, q;
     61     while (scanf("%d%d", &n, &q) != EOF)
     62     {
     63         memset(sum, 0, sizeof(sum));
     64         for (int i = 0; i < n; ++i)
     65         {
     66             scanf("%d", &a[i]);
     67             b[i] = a[i];
     68         }
     69         for (int i = 0; i < q; ++i)
     70         {
     71             scanf("%d%d", &Q[i].l, &Q[i].r);
     72             Q[i].l--;
     73             Q[i].r--;
     74             Q[i].id = i;
     75         }
     76         sort(a, a + n);
     77         sort(Q, Q + q);
     78         n = unique(a, a + n) - a;
     79         //printf("%d
    ", n);
     80         for (int i = 0; i < n; ++i)
     81         {
     82             mark[a[i]] = i + 1;
     83             //printf("%d %d
    ", a[i], i + 1);
     84         }
     85         int preL = 0;
     86         int preR = 0;
     87         int t;
     88         int tmp = 0;
     89         for (int i = 0; i < q; ++i)
     90         {
     91             if (preR - 1 > Q[i].r)//第二种情况, 清空树状数组
     92             {
     93                 memset(sum, 0, sizeof(sum));
     94                 preR = Q[i].l;
     95                 preL = Q[i].l;
     96                 tmp = 0;
     97             }
     98             for (int j = preL; j < Q[i].l; ++j)//减去左边的区间
     99             {
    100                 tmp -= getSum(mark[b[j]]-1);
    101                 modify(mark[b[j]], -1, mark[a[n - 1]]);
    102                 preL = Q[i].l;
    103                 
    104             }
    105             
    106             for (int j = preR; j <= Q[i].r; ++j)
    107             {
    108                 
    109                 modify(mark[b[j]], 1, mark[a[n-1]]);
    110                 tmp += getSum(mark[a[n-1]])-getSum(mark[b[j]]);
    111             }
    112             preR = Q[i].r + 1;
    113             ans[Q[i].id] = tmp;
    114         }
    115         for (int i = 0; i < q; ++i)
    116             printf("%d
    ", ans[i]);
    117     }
    118     return 0;
    119 }
    View Code

    正解应该是。

    设ans1[i][j] 为区间i-->j,包含a[i]的逆序对数,  首先我们暴力算好ans1[i][j] ,时间复杂度为O(N*N)

    设ans2[i][j] 为区间i-->j中的逆序对数,

    那么ans2[i][j] = ans1[i][j] + ans[i+1][j] +...+ans[j][j]

    优化一下就是, 如果ans2[i+1][j] 已经算好了,  那么ans2[i][j] = ans2[i+1][j] + ans1[i][j];

    所以这个的时间复杂度也是O(N*N),而且 ans1 和ans2可以合成一个数组

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <queue>
     7 #include <stack>
     8 #include <vector>
     9 #include <map>
    10 #include <set>
    11 #include <string>
    12 #include <math.h>
    13 using namespace std;
    14 #pragma warning(disable:4996)
    15 typedef long long LL;                   
    16 const int INF = 1<<30;
    17 /*
    18 
    19 */
    20 const int N = 1000 + 10;
    21 int ans[N][N]; 
    22 int a[N];
    23 int main()
    24 {
    25     int n, q;
    26     while (scanf("%d%d", &n, &q) != EOF)
    27     {
    28         for (int i = 1; i <= n; ++i)
    29             scanf("%d", &a[i]);
    30 
    31         //这里的ans[i][j] 表示区间i-->j, 包含元素a[i]的逆序对数
    32         for (int i = 1; i <= n; ++i)
    33         for (int j = i; j <= n; ++j)
    34             ans[i][j] += ans[i][j - 1] + (a[i] > a[j] ? 1 : 0);
    35 
    36         //那么 ans[i][j] 要表示区间i-->j的逆序对数时, ans[i][j] += ans[i+1][j] + ans[i+2][j]+...+ans[j][j]
    37         // 如果ans[i+1][j]已经算出来了,  那么ans[i][j] += ans[i+1][j] 即可,  因为贡献是后缀和性质的
    38         for (int j = 1; j <= n; ++j)
    39         for (int i = j; i >= 1; --i)
    40             ans[i][j] += ans[i + 1][j];
    41         int l, r;
    42         while (q--)
    43         {
    44             scanf("%d%d", &l, &r);
    45             printf("%d
    ", ans[l][r]);
    46         }
    47     }
    48     return 0;
    49 }
    View Code

    1003

    给我们一棵树,每个节点都有权值, 有两个操作

    0 x y ,  将节点x的权值改为y

    1 x y   询问x->y 的路径上, 是否有权值的次数出现奇数次(保证最多只有一个奇数次) 如果没有,输出-1, 如果有, 输出那个权值

    任意两点的路径, 可以用lca求出, 然后要求权值是不是出现奇数次, 可以用异或,   a^a = 0  ,  a^a^a=a,

    然而这并没有什么用,TLE, 如果树退化成链, 那么每次询问的时间复杂度是O(N),每次询问的复杂度要O(logN)才行

      1 #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <stdlib.h>
      5 #include <algorithm>
      6 #include <iostream>
      7 #include <queue>
      8 #include <stack>
      9 #include <vector>
     10 #include <map>
     11 #include <set>
     12 #include <string>
     13 #include <math.h>
     14 using namespace std;
     15 #pragma warning(disable:4996)
     16 typedef long long LL;                   
     17 const int INF = 1<<30;
     18 /*
     19 RE
     20 */
     21 const int N = 100000 + 10;
     22 struct Edge
     23 {
     24     int to, next;
     25 }g[N];
     26 
     27 int value[N], head[N], e, parent[N], depth[N];
     28 void addEdge(int a, int b)
     29 {
     30     g[e].to = b;
     31     g[e].next = head[a];
     32     head[a] = e++;
     33 }
     34 void dfs(int u, int fa, int d)
     35 {
     36     depth[u] = d;
     37     for (int i = head[u]; i != -1; i = g[i].next)
     38     {
     39         int v = g[i].to;
     40         if (v == fa) continue;
     41         dfs(v, u,d + 1);
     42     }
     43 }
     44 
     45 int solve(int x, int y)
     46 {
     47     if (x == y)
     48         return value[x];
     49     int ret = 0;
     50     ret ^= value[x];
     51     //ret ^= value[y];
     52     if (depth[x] < depth[y])
     53         swap(x, y); 
     54     int t = y;
     55     int d = depth[x];
     56     while(d > depth[y])
     57     {
     58         x = parent[x];
     59         d--;
     60         ret ^= value[x];
     61     }
     62     while (x!=y)
     63     {
     64         x = parent[x];
     65         y = parent[y];
     66         ret ^= value[x];
     67         ret ^= value[y];
     68     }
     69     if (t != y)
     70         ret ^= value[y];
     71     return ret;
     72 
     73 }
     74 int main()
     75 {
     76     int t, n, q, a, b, op;
     77     scanf("%d", &t);
     78     while (t--)
     79     {
     80         memset(parent, -1, sizeof(parent));
     81         memset(depth, 0, sizeof(depth));
     82         memset(head, -1, sizeof(head));
     83         e = 0;
     84         scanf("%d%d", &n, &q);
     85         for (int i = 1; i < n; ++i)
     86         {
     87             scanf("%d%d", &a, &b);
     88             addEdge(a, b);
     89             addEdge(b, a);
     90             parent[b] = a;
     91 
     92         }
     93         int root = 1;
     94         while (parent[root] != -1)
     95             root = parent[root];
     96         dfs(root,-1,1);
     97         for (int i = 1; i <= n; ++i)
     98         {
     99             scanf("%d", &value[i]);
    100             value[i]++;
    101         }
    102         for (int i = 0; i < q; ++i)
    103         {
    104             scanf("%d%d%d", &op, &a, &b);
    105             if (op == 0)
    106                 value[a] = b;
    107             else
    108             {
    109                 int ret = solve(a, b);
    110                 printf("%d
    ", ret ? ret-1 : -1);
    111             }
    112         }
    113     }
    114     return 0;
    115 }
    View Code

    题解说这题要用树链剖分, 然后我并不懂

  • 相关阅读:
    20191318实验四 《Python程序设计》实验报告
    20191318实验三 Socket编程技术
    20191318实验二 Python程序设计入门
    实验一 Python程序设计入门
    《信息安全专业导论》第十二周学习总结
    《信息安全专业导论》第十一周学习总结
    markdown画思维导图
    markdown页面内跳转
    20191206 2019-2020-2 《Python程序设计》实验四报告
    20191206 实验三《Python程序设计》实验报告
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4591701.html
Copyright © 2011-2022 走看看