• codeforces 400E. Inna and Binary Logic 线段树


    题目链接

    给出n个数, 定义a[1][i]为这初始的n个数, 然后a[i][j] = a[i-1][j]&a[i-1][j-1], 这样就可以得到一个三角形一共n*(n-1)/2个数。

    给出一种操作, 将a[1][x]这个位置的数换为y, 然后求换完之后的这n(n-1)/2个数的和。

    很有意思的题, 这个题应该按位建线段树, 这样需要建18棵, 因为a[1][i]的最大值为1e5。

    然后我们来看具体如何做, 我们来看一组数据:3 6 7, 换为二进制之后是下面这个样子。

    0 1 1

    1 1 0

    1 1 1

    我们先来算一算这三个数的值为多少, 3+6+7+2+6+2 = 26。

    我们发现第一个数和第二个数&之后剩余的是2, 第二个数和第三个数&之后剩余的是6, 我们来观察二进制, 发现第一个数和第二个数的第二位的2个1是相邻的, 并且这一位换成10进制正好是2, 而第二个数和第三个数的第一位和第二位的两个1是相邻的, 换成10进制之后是6。

    由此可以推断出, 如果是一个单独的1, 那么贡献就是1, 两个相邻的1贡献是2*3/2 = 3,n个相邻的1贡献就是n(n+1)/2。

    那么我们建立线段树的时候就应该保存一个sum, prefix, 以及suffix, 具体的看代码。

     1 #include <iostream>
     2 #include <vector>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <cmath>
     7 #include <map>
     8 #include <set>
     9 #include <string>
    10 #include <queue>
    11 #include <stack>
    12 #include <bitset>
    13 using namespace std;
    14 #define pb(x) push_back(x)
    15 #define ll long long
    16 #define mk(x, y) make_pair(x, y)
    17 #define lson l, m, rt<<1
    18 #define mem(a) memset(a, 0, sizeof(a))
    19 #define rson m+1, r, rt<<1|1
    20 #define mem1(a) memset(a, -1, sizeof(a))
    21 #define mem2(a) memset(a, 0x3f, sizeof(a))
    22 #define rep(i, n, a) for(int i = a; i<n; i++)
    23 #define fi first
    24 #define se second
    25 typedef pair<int, int> pll;
    26 const double PI = acos(-1.0);
    27 const double eps = 1e-8;
    28 const int mod = 1e9+7;
    29 const int inf = 1061109567;
    30 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    31 const int maxn = 1e5+5;
    32 ll cal(ll val) {
    33     return 1LL*val*(val+1)/2;
    34 }
    35 struct SegmentTree
    36 {
    37     ll sum[maxn<<2], pre[maxn<<2], suf[maxn<<2];
    38     void pushUp(int rt, int m) {
    39         sum[rt] = sum[rt<<1|1] + sum[rt<<1];
    40         if(pre[rt<<1|1]&&suf[rt<<1]) {
    41             sum[rt] += cal(pre[rt<<1|1]+suf[rt<<1])-cal(suf[rt<<1])-cal(pre[rt<<1|1]); 
    42         }     
    43         pre[rt] = pre[rt<<1];
    44         suf[rt] = suf[rt<<1|1];
    45         if(pre[rt] == m-(m>>1)) {
    46             pre[rt] += pre[rt<<1|1];
    47         }
    48         if(suf[rt] == m>>1) {
    49             suf[rt] += suf[rt<<1];
    50         }
    51     }
    52     void update(int p, int val, int l, int r, int rt) {
    53         if(l == r) {
    54             sum[rt] = pre[rt] = suf[rt] = val;
    55             return ;
    56         }
    57         int m = l+r>>1;
    58         if(p<=m)
    59             update(p, val, lson);
    60         else
    61             update(p, val, rson);
    62         pushUp(rt, r-l+1);
    63     }
    64 }tree[18];
    65 int main()
    66 {
    67     int cnt, n, m, x, y, a[20];
    68     cin>>n>>m;
    69     for(int i = 1; i<=n; i++) {
    70         scanf("%d", &x);
    71         cnt = 0;
    72         while(x) {
    73             a[cnt++] = x&1;
    74             x>>=1;
    75         }
    76         for(int j = 0; j<cnt; j++) {
    77             tree[j].update(i, a[j], 1, n, 1);
    78         }
    79     }
    80     while(m--) {
    81         scanf("%d%d", &x, &y);
    82         cnt = 0;
    83         mem(a);
    84         while(y) {
    85             a[cnt++] = y&1;
    86             y>>=1;
    87         }
    88         ll ans = 0, mul = 1;
    89         for(int i = 0; i<18; i++) {
    90             tree[i].update(x, a[i], 1, n, 1);
    91             ans += tree[i].sum[1]*mul;
    92             mul*=2;
    93         }
    94         cout<<ans<<endl;
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    selenium WebDriver 清空input的方式
    selenium 获取input输入框中的值的方法
    webdriver报不可见元素异常方法总结
    git踩过的坑
    what's the 数据结构
    算法进阶——贪心与动态规划
    what's the 二叉树
    算法基础——列表排序
    算法基础——列表查找
    Flask项目示例目录
  • 原文地址:https://www.cnblogs.com/yohaha/p/5088942.html
Copyright © 2020-2023  润新知