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\n", 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\n", 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\n");
        // std::cout << tree[id].bt << endl;
        ex = tree[id].bt >> m;
        tree[id].bt |= ex;
        // printf("3\n");
        // std::cout << tree[id].bt << endl;
        tree[id].bt &= C;
        // printf("id=%d l=%d r=%d x=%d y=%d val=%d \n", 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\n", 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\n", 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\n", 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

 

posted @ 2019-07-24 17:01  EchoZQN  阅读(152)  评论(0编辑  收藏  举报