• CF Manthan, Codefest 16 G. Yash And Trees 线段树+bitset


    题目链接:http://codeforces.com/problemset/problem/633/G

    大意是一棵树两种操作,第一种是某一节点子树所有值+v,第二种问子树中节点模m出现了多少种m以内的质数。

    第一种操作非常熟悉了,把每个节点dfs过程中的pre和post做出来,对序列做线段树。维护取模也不是问题。第二种操作,可以利用bitset记录质数出现情况。所以整个线段树需要维护bitset的信息。

    对于某一个bitset x,如果子树所有值需要加y,则x=(x<<y)|(x>>(m-y))

    一开始写挂了几次,有一点没注意到,因为我bitset直接全都是1000,而不是m,所以上面式子左移会有问题,解决方法是做一个0到m每位都是1的全集,或者表示质数集的bitset上限做到m。

      1 #include <iostream>
      2 #include <vector>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <math.h>
      8 #include <stdlib.h>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #include <ctime>
     14 #include <numeric>
     15 #include <bitset>
     16 #include <cassert>
     17 
     18 using namespace std;
     19 const int N=123456;
     20 int a[N];
     21 vector<int>edge[N];
     22 bitset<1000>bs[N<<2];
     23 bitset<1000>prime;
     24 int mark[N<<2];
     25 int L[N],R[N];
     26 int dfn=0;
     27 int m;
     28 int id[N];
     29 void dfs(int u,int f) {
     30     L[u]=++dfn;
     31     id[dfn]=u;
     32     for (int i=0;i<edge[u].size();i++) {
     33         int v=edge[u][i];
     34         if (v==f)
     35             continue;
     36         dfs(v,u);
     37     }
     38     R[u]=dfn;
     39 }
     40 void up(int rt) {
     41     bs[rt]=(bs[rt<<1]|bs[rt<<1|1]);
     42 }
     43 void add(int rt,int x) {
     44     bs[rt]=(((bs[rt]<<x))|(bs[rt]>>(m-x)));
     45 }
     46 void down(int rt) {
     47     if (mark[rt]) {
     48         add(rt<<1,mark[rt]);
     49         add(rt<<1|1,mark[rt]);
     50         mark[rt<<1]=(mark[rt<<1]+mark[rt])%m;
     51         mark[rt<<1|1]=(mark[rt<<1|1]+mark[rt])%m;
     52         mark[rt]=0;
     53     }
     54 }
     55 void build(int l,int r,int rt) {
     56     mark[rt]=0;
     57     if (l==r) {
     58         int x=a[id[l]];
     59         bs[rt].set(x);
     60         return;
     61     }
     62     int m=(l+r)>>1;
     63     build(l,m,rt<<1);
     64     build(m+1,r,rt<<1|1);
     65     up(rt);
     66 }
     67 
     68 void upd(int L,int R,int x,int l,int r,int rt) {
     69     if (L<=l&&r<=R) {
     70         add(rt,x);
     71         mark[rt]=(mark[rt]+x)%m;
     72         return;
     73     }
     74     down(rt);
     75     int m=(l+r)>>1;
     76     if (L<=m)
     77         upd(L,R,x,l,m,rt<<1);
     78     if (R>m)
     79         upd(L,R,x,m+1,r,rt<<1|1);
     80     up(rt);
     81 }
     82 bitset<1000> ans;
     83 void ask(int L,int R,int l,int r,int rt) {
     84      if (L<=l&&r<=R) {
     85         ans|=bs[rt];
     86         return;
     87     }
     88     down(rt);
     89     int m=(l+r)>>1;
     90     if (L<=m)
     91         ask(L,R,l,m,rt<<1);
     92     if (R>m)
     93         ask(L,R,m+1,r,rt<<1|1);
     94 }
     95 
     96 int main () {
     97     int n;
     98     scanf("%d %d",&n,&m);
     99     for (int i=2;i<m;i++) {
    100         bool isp=true;
    101         for (int j=2;isp&&j*j<=i;j++) {
    102             if (i%j==0)
    103                 isp=false;
    104         }
    105         if (isp){
    106             prime.set(i);
    107         }
    108     }
    109     for (int i=1;i<=n;i++){
    110         scanf("%d",a+i);
    111         a[i]%=m;
    112     }
    113     for (int i=1;i<n;i++) {
    114         int u,v;
    115         scanf("%d %d",&u,&v);
    116         edge[u].push_back(v);
    117         edge[v].push_back(u);
    118     }
    119     dfn=0;
    120     dfs(1,-1);
    121     build(1,n,1);
    122     int Q;
    123     scanf("%d",&Q);
    124     while (Q--) {
    125         int op;
    126         scanf("%d",&op);
    127         if (op==1) {
    128             int u,x;
    129             scanf("%d %d",&u,&x);
    130             x%=m;
    131             upd(L[u],R[u],x,1,n,1);
    132         }
    133         else {
    134             int u;
    135             scanf("%d",&u);
    136             ans=0;
    137             ask(L[u],R[u],1,n,1);
    138             ans&=prime;
    139             int ret=ans.count();
    140             printf("%d
    ",ret);
    141         }
    142     }
    143     return 0;
    144 }
    View Code
  • 相关阅读:
    cli create ssl certkey
    开启HSTS让浏览器强制跳转HTTPS访问
    Down State Flush Feature
    tasklist、taskkill命令使用
    findstr 命令使用
    【批处理学习笔记】第十一课:常用DOS命令(1)
    【批处理学习笔记】第十课:批处理符号(3)
    【批处理学习笔记】第九课:批处理符号(2)
    【批处理学习笔记】第八课:批处理符号(1)
    【批处理学习笔记】第七课:简单的批处理命令(6)
  • 原文地址:https://www.cnblogs.com/micrari/p/5229393.html
Copyright © 2020-2023  润新知