JZOJ 5943. 树

Posted traveller-ly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ 5943. 树相关的知识,希望对你有一定的参考价值。

Description

技术分享图片
 

Input

第一行一个整数 n 表示序列长度, 接下来一行 n 个整数描述这个序列.
第三行一个整数 q 表示操作次数, 接下来 q 行每行一次操作, 格式同题目描述.

Output

       输出等同于操作 2, 3 次数之和的行数, 每行一个非负整数表示对应询问的答案. 注意操作 2 的答案不需要进行取模.
 

Sample Input

Sample Input1
5
8 4 3 5 6
5
2 3 5
3 1 2
1 2 4 3
2 3 5
3 1 2

样例 2
见下发文件中的 ex_seg2.in/out.

 

Sample Output

Sample Output1
14
608
10
384

样例 1 解释
第三次操作后, 序列变为 [8, 0, 3, 1, 6].

 
 做法:显然修改只会让数变小, 每个数只会变小 log 次, 所以我们线段树维护区间或起来的值判断是 否需要修改, 如果需要就暴力下去修改. 复杂度 O(nlog2n) 对于操作 3 直接把式子展开, 再维护一个区间平方和即可
技术分享图片
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #define mo 998244353
  5 #define LL long long
  6 #define N 100007
  7 using namespace std;
  8 struct tree{
  9     LL s,sum1,sum2;
 10     int l,r;
 11 }e[N*4];
 12 int n,q,a[N];
 13 LL ans,sum;
 14 
 15 int read(){
 16     int s=0;
 17     char ch=getchar();
 18     for(;ch<0||ch>9;ch=getchar());
 19     for(;ch>=0&&ch<=9;s=s*10+ch-0,ch=getchar());
 20     return s;
 21 }
 22 
 23 inline void Build(int p,int l,int r){
 24     if (l==r){
 25         e[p].l=l,e[p].r=r;
 26         e[p].s=a[l];
 27         e[p].sum1=a[l];
 28         e[p].sum2=e[p].s*e[p].s%mo;
 29         return;
 30     }
 31     int mid=(l+r)>>1;
 32     Build(p<<1,l,mid);
 33     Build(p<<1|1,mid+1,r);
 34     e[p].l=l;
 35     e[p].r=r;
 36     e[p].s=e[p<<1].s|e[p<<1|1].s;
 37     e[p].sum1=e[p<<1].sum1+e[p<<1|1].sum1;
 38     e[p].sum2=(e[p<<1].sum2+e[p<<1|1].sum2)%mo;
 39 }
 40 
 41 void Init(){
 42     n=read();
 43     for(int i=1;i<=n;i++) a[i]=read();
 44     Build(1,1,n);
 45     q=read();
 46 }
 47 
 48 void query(int p,int l,int r){
 49     if (e[p].l>=l&&e[p].r<=r){
 50         ans+=e[p].sum1;
 51         return;
 52     }
 53     int mid=(e[p].l+e[p].r)>>1;
 54     if (mid>=r) query(p<<1,l,r);
 55     else if(mid<l)    query(p<<1|1,l,r);
 56     else query(p<<1,l,r),query(p<<1|1,l,r);
 57 }
 58 
 59 void update(int p,int l,int r,int x){
 60     if ((e[p].s&x)==e[p].s)    return;
 61     if (e[p].l==e[p].r){
 62         e[p].s&=x;
 63         e[p].sum1=e[p].s;
 64         e[p].sum2=e[p].s*e[p].s%mo;
 65         return;
 66     }
 67     int mid=(e[p].l+e[p].r)>>1;
 68     if (mid>=r) update(p<<1,l,r,x);
 69     else if(mid<l) update(p<<1|1,l,r,x);
 70     else update(p<<1,l,r,x),update(p<<1|1,l,r,x);
 71     e[p].s=e[p<<1].s|e[p<<1|1].s;
 72     e[p].sum1=e[p<<1].sum1+e[p<<1|1].sum1;
 73     e[p].sum2=(e[p<<1].sum2+e[p<<1|1].sum2)%mo;
 74 }
 75 
 76 void chaxun(int p,int l,int r){
 77     if (e[p].l>=l&&e[p].r<=r){
 78         sum=(sum+e[p].sum2)%mo;
 79         return;
 80     }
 81     int mid=(e[p].l+e[p].r)>>1;
 82     if (mid>=r) chaxun(p<<1,l,r);
 83     else if(mid<l)    chaxun(p<<1|1,l,r);
 84     else chaxun(p<<1,l,r),chaxun(p<<1|1,l,r);
 85 }
 86 
 87 int main(){
 88     freopen("seg.in","r",stdin);
 89     freopen("seg.out","w",stdout);
 90     Init();
 91     while(q--){
 92         int x,y,l,r;
 93         x=read();
 94         if (x==1){
 95             l=read(),r=read(),y=read();
 96             update(1,l,r,y);
 97         }
 98         if (x==2){
 99             l=read(),r=read();
100             ans=0;
101             query(1,l,r);
102             printf("%lld
",ans);
103         }
104         if (x==3){
105             l=read(),r=read();
106             sum=0;
107             ans=0;
108             query(1,l,r);
109             chaxun(1,l,r);
110             ans%=mo;
111             sum%=mo;
112             printf("%lld
",(sum*(r-l+1)%mo*2%mo+(ans*ans)%mo*2)%mo);
113         }
114     }
115 }
View Code

 


以上是关于JZOJ 5943. 树的主要内容,如果未能解决你的问题,请参考以下文章

[线段树]JZOJ 5812

JZOJ4605. 排序(线段树合并与分裂)

JZOJ 3894. 改造二叉树

[扫描线][倍增][dfs序][线段树] Jzoj P6276 树

[线段树]JZOJ 1214 项链工厂

jzoj6276. noip提高组模拟1树