zoukankan      html  css  js  c++  java
  • G. Yash And Trees 线段树 + dfs序 + bitset

    这个是要用bitset 一个大整数的二进制  学习推荐博客

    这个题目大意就是:给你n,m 还有一个序列,还有一个一棵树,有一种操作一种询问

    操作是给你一个节点 把这个节点及其子节点都加上x

    询问是 给你一个节点,问你这个节点以下 小于m的质数有多少种,注意是种,所以要去重,所以需要bitset

    这个题目我写了一上午,wa了一下午,在lj的帮助之下终于写出来了。

    写法,操作就可以用<< 来代替加上x,但是因为如果超出了m,就要对m取模,所以相当于一个环,这个环的处理要注意。

    注意:

    我wa的地方:

    忘记了update 的push_up 操作,

    query的两个区间合起来的时候没有去重。

    还有就是 << 这个操作,因为素数一定要小于m,而且每一个数一定小于m,所以<<m,就可以了,而且素数的bitset 只要到m-1就可以了

    最后一个最重要的!!!

    我建树建错了,这个dfs序之后,如果我想把给的a序列放进来,那么就需要按照dfs序来,所以dfs序,不仅仅要存每一个数映射的位置,而且要存每一个位置存的数。

    建树要注意!!! 第一次碰到这个问题,以后希望不要再这样wa一下午了,

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <bitset>
    #include <vector>
    #include <queue>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 10;
    const int mx = 2200;
    bitset<mx>B;
    bitset<mx>C;
    bitset<mx>ex;
    struct node
    {
        bitset<mx>bt;
        ll lazy;
    }tree[maxn*4];
    int n, m, q, p[maxn];
    ll a[maxn];
    //素数筛
    void init() {
        for (int i = 2; i < maxn; i++) p[i] = 1;
        for (int i = 2; i*i < maxn; i++) {
            if (p[i]) {
                for (int j = i * i; j < maxn; j += i) {
                    p[j] = 0;
                }
            }
        }
        B.reset(); C.reset();
        for (int i = 0; i < m; i++) {
            if (p[i]) B.set(i);//B构造出一个全部都是素数的bitset
            C.set(i);
        }
    }
    //v数组记录每一个i的最小质因数,isp记录所有的质数
    int er[maxn], el[maxn], tot;
    vector<int>G[maxn];
    bool vis[maxn];
    int num[maxn];
    //dfs序 转化成二叉树
    void dfs(int x)
    {
        vis[x] = 1;
        el[x] = ++tot;
        num[tot] = x;
        for(int i=0;i<G[x].size();i++)
        {
            int v = G[x][i];
            if (vis[v]) continue;
            dfs(v);
        }
        er[x] = tot;
    }
     
    //线段树的建树过程
    void build(int id,int l,int r)
    {
        tree[id].lazy = 0;
        if(l==r)
        {
            tree[id].bt.set(a[num[l]]);
            return;
        } 
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        tree[id].bt = tree[id << 1].bt | tree[id << 1 | 1].bt;
        // printf("id=%d l=%d r=%d
    ", id, l, r);
        // std::cout << tree[id].bt << endl;
    }
    void push_down(int id)
    {
        if(tree[id].lazy)
        {
            ex.reset();
            int val = tree[id].lazy;
            tree[id << 1].bt <<= val;
            ex = tree[id << 1].bt >> m;
            tree[id << 1].bt |= ex;
            tree[id << 1].bt &= C;
     
            tree[id << 1].lazy += val;
            tree[id << 1].lazy %= m;
     
            ex.reset();
            tree[id << 1 | 1].bt <<= val;
            ex = tree[id << 1 | 1].bt >> m;
            tree[id << 1 | 1].bt |= ex;
            tree[id << 1 | 1].bt &= C;
     
            tree[id << 1 | 1].lazy += val;
            tree[id << 1 | 1].lazy %= m;
     
            tree[id].lazy = 0;
        }
    }
     
    void update(int id,int l,int r,int x,int y,int val)
    {
        if(x<=l&&y>=r)
        {
            // printf("1 id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
            // std::cout << tree[id].bt << endl;
            ex.reset();
            tree[id].lazy += val;
            tree[id].lazy %= m;
     
            tree[id].bt <<= val;
            // printf("2
    ");
            // std::cout << tree[id].bt << endl;
            ex = tree[id].bt >> m;
            tree[id].bt |= ex;
            // printf("3
    ");
            // std::cout << tree[id].bt << endl;
            tree[id].bt &= C;
            // printf("id=%d l=%d r=%d x=%d y=%d val=%d 
    ", id, l, r, x, y, val);
            // std::cout << tree[id].bt << endl;
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        if (x <= mid) update(id << 1, l, mid, x, y, val);
        if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, val);
        tree[id].bt = tree[id << 1].bt | tree[id << 1 | 1].bt;
    }
     
    bitset<mx> query(int id,int l,int r,int x,int y)
    {
        if (x <= l && y >= r) {
            // printf("id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
            // std::cout << tree[id].bt << endl;
            return tree[id].bt&B;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        bitset<mx>ans;
        if (x <= mid) ans |= query(id << 1, l, mid, x, y);
        if (y > mid) ans |= query(id << 1 | 1, mid + 1, r, x, y);
        // printf("id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
        // std::cout << ans << endl;
        return (ans & B);
    }
     
    int main()
    {
        tot = 0;
        scanf("%d%d", &n, &m);
        init();
        for (int i = 1; i <= n; i++) scanf("%lld", &a[i]), a[i] %= m;
        for(int i=1;i<n;i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        memset(vis, 0, sizeof(vis));
        dfs(1);
        build(1, 1, n);
        scanf("%d", &q);
        while(q--)
        {
            int opt, v, x;
            scanf("%d", &opt);
            if(opt==1)
            {
                scanf("%d%d", &v, &x);
                x %= m;
                update(1, 1, n, el[v], er[v], x);
            }
            else
            {
                scanf("%d", &v);
                bitset<mx>ans = query(1, 1, n, el[v], er[v]);
                printf("%d
    ", ans.count());
            }
        }
        return 0;
    }
     
    /*
    3 33
    94 21 38
    3 1
    3 2
    9
    2 1
    2 2
    1 3 127
    2 2
    1 2 381
    1 1 275
    2 2
    2 3
    1 1 695
     
     */
    bitset
  • 相关阅读:
    常用PHP array数组函数
    每天学习30分钟新知识之html教程1
    laravel学习之路2: jwt集成
    JWT简介json web token bear token
    MDwiki 调研
    laravel学习之路1:认证相关
    OAuth 2.0介绍
    第一行代码 6.4 数据存储全方案-详解持久化数据- 数据库
    github(1)安装及使用图文详解
    Android集成讯飞语音、百度语音、阿里语音识别
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11239270.html
Copyright © 2011-2022 走看看