zoukankan      html  css  js  c++  java
  • ZOJ 3911 Prime Query(线段树)

    Prime Query

    Time Limit: 1 Second      Memory Limit: 196608 KB

    You are given a simple task. Given a sequence A[i] with N numbers. You have to perform Q operations on the given sequence.

    Here are the operations:

    • A v l, add the value v to element with index l.(1<=V<=1000)
    • R a l r, replace all the elements of sequence with index i(l<=i<= r) with a(1<=a<=10^6) .
    • Q l r, print the number of elements with index i(l<=i<=r) and A[i] is a prime number

    Note that no number in sequence ever will exceed 10^7.

    Input

    The first line is a signer integer T which is the number of test cases.

    For each test case, The first line contains two numbers N and Q (1 <= N, Q <= 100000) - the number of elements in sequence and the number of queries.

    The second line contains N numbers - the elements of the sequence.

    In next Q lines, each line contains an operation to be performed on the sequence.

    Output

    For each test case and each query,print the answer in one line.

    Sample Input

    1
    5 10
    1 2 3 4 5
    A 3 1      
    Q 1 3
    R 5 2 4
    A 1 1
    Q 1 1
    Q 1 2
    Q 1 4
    A 3 5
    Q 5 5
    Q 1 5
    

    Sample Output

    2
    1
    2
    4
    0
    4

    来自 <http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3911>

    【题意】:

    单点修改,区间修改,查询区间素数个数

    【解题思路】:

    维护线段树,结点内容为:Val-实时数值(只针对单点)  Sum-区间素数个数  Lazy-区间修改后传递给子区间 

    关键点在于数值和素数标记的同时更新和传递,由于区间更新时没有直接更新到最底层,故单点查询也需要pushdown操作。这里选择将区间更新后的值直接下传,至于素数标记,下传后再进行判断并赋值。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #define mid(a,b) ((a+b)>>1)
      7 #define LL int
      8 #define maxn 110000
      9 #define IN freopen("in.txt","r",stdin);
     10 using namespace std;
     11 
     12 char is_prime[maxn*100];
     13 void sieve()
     14 {
     15     int m=(int)sqrt((maxn*100)+0.5);
     16     fill(is_prime,is_prime+(maxn*100),1);
     17     is_prime[0]=is_prime[1]=0;
     18     for(int i=2;i<=m;i++) if(is_prime[i])
     19         for(int j=i*i;j<(maxn*100);j+=i) is_prime[j]=0;
     20 }
     21 
     22 int n,q;
     23 LL num[maxn];
     24 struct Tree
     25 {
     26     int left,right;
     27     LL sum;
     28     LL val,lazy;
     29 }tree[maxn<<2];
     30 
     31 
     32 /*递归建树*/
     33 void build(int i,int left,int right)
     34 {
     35     tree[i].left=left;
     36     tree[i].right=right;
     37     tree[i].lazy=0;
     38 
     39     if(left==right){
     40         tree[i].val=num[left];
     41         tree[i].sum=(is_prime[num[left]]? 1:0);
     42         return ;
     43     }
     44 
     45     int mid=mid(left,right);
     46 
     47     build(i<<1,left,mid);
     48     build(i<<1|1,mid+1,right);
     49 
     50     tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
     51 }
     52 
     53 /*区间修改,标记下传:每当访问到当前结点的子节点时,下传标记*/
     54 void pushdown(int i)
     55 {
     56     if(tree[i].lazy){
     57         int tmp = (is_prime[tree[i].lazy]? 1:0);
     58         tree[i<<1].val=tree[i].lazy;
     59         tree[i<<1|1].val=tree[i].lazy;
     60         tree[i<<1].lazy=tree[i].lazy;
     61         tree[i<<1|1].lazy=tree[i].lazy;
     62         tree[i<<1].sum=(tree[i<<1].right-tree[i<<1].left+1)*tmp;
     63         tree[i<<1|1].sum=(tree[i<<1|1].right-tree[i<<1|1].left+1)*tmp;
     64         tree[i].lazy=0; /*下传后清零*/
     65     }
     66 }
     67 
     68 /*区间修改,d为改变量*/
     69 void update(int i,int left,int right,LL d)
     70 {
     71     if(tree[i].left==left&&tree[i].right==right)
     72     {
     73         int tmp = (is_prime[d]? 1:0);
     74         tree[i].sum=(right-left+1)*tmp;
     75         tree[i].val=d;
     76         tree[i].lazy=d;
     77         return ;
     78     }
     79 
     80     pushdown(i);
     81 
     82     int mid=mid(tree[i].left,tree[i].right);
     83 
     84     if(right<=mid) update(i<<1,left,right,d);
     85     else if(left>mid) update(i<<1|1,left,right,d);
     86     else
     87     {
     88         update(i<<1,left,mid,d);
     89         update(i<<1|1,mid+1,right,d);
     90     }
     91 
     92     tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
     93 }
     94 
     95 /*单点修改,d为改变量*/
     96 void update(int i,int x,LL d)
     97 {
     98     if(tree[i].left==tree[i].right){
     99         tree[i].val+=d;
    100         tree[i].sum=(is_prime[tree[i].val]? 1:0);
    101         return;
    102     }
    103 
    104     pushdown(i);
    105     int mid=mid(tree[i].left,tree[i].right);
    106 
    107     if(x<=mid) update(i<<1,x,d);
    108     else update(i<<1|1,x,d);
    109 
    110     tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
    111 }
    112 
    113 /*区间结果查询*/
    114 LL query(int i,int left,int right)
    115 {
    116     if(tree[i].left==left&&tree[i].right==right)
    117         return tree[i].sum;
    118 
    119     pushdown(i);
    120 
    121     int mid=mid(tree[i].left,tree[i].right);
    122 
    123     if(right<=mid) return query(i<<1,left,right);
    124     else if(left>mid) return query(i<<1|1,left,right);
    125     else return query(i<<1,left,mid)+query(i<<1|1,mid+1,right);
    126 }
    127 
    128 
    129 int main(int argc, char const *argv[])
    130 {
    131     //IN;
    132 
    133     sieve();
    134     int t;scanf("%d",&t);
    135     while(t--)
    136     {
    137         scanf("%d %d",&n,&q);
    138         for(int i=1;i<=n;i++) scanf("%d",&num[i]);
    139         build(1,1,n);
    140 
    141         while(q--)
    142         {
    143             char c;
    144             while(c=getchar()){
    145                 if(c=='A'||c=='R'||c=='Q') break;
    146             }
    147             if(c=='A'){
    148                 int v,l;
    149                 scanf("%d %d",&v,&l);
    150                 update(1,l,v);
    151             }
    152             if(c=='R'){
    153                 int a,l,r;
    154                 scanf("%d %d %d",&a,&l,&r);
    155                 update(1,l,r,a);
    156             }
    157             if(c=='Q'){
    158                 int l,r;
    159                 scanf("%d %d",&l,&r);
    160                 printf("%d
    ", query(1,l,r));
    161             }
    162         }
    163     }
    164 
    165     return 0;
    166 }
  • 相关阅读:
    一条短信控制你的手机! Android平台的SQL注入漏洞浅析
    技术分享 Android动态调试程序
    [Java] java byte数组与int,long,short,byte转换
    技术分享:. 外部动态加载DEX文件风险浅谈
    TestLink的使用
    selenium_页面设计模式PageFactory与动态Xpath
    selenium_maven高级实战
    selenium_Jenkins高级实战篇
    将本地Git仓库中的内容上传至GitHub
    将本地下载的jar导入到本地的私有仓库中
  • 原文地址:https://www.cnblogs.com/Sunshine-tcf/p/5006073.html
Copyright © 2011-2022 走看看