zoukankan      html  css  js  c++  java
  • LOJ2251 [ZJOI2017] 树状数组【线段树】【树套树】

    题目分析:

    对于一个$add$操作,它的特点是与树状数组的查询相同,会给$1$到它自己产生影响,而$query$操作则会途径所有包含它的树状数组点。现在$add$操作具有前向性(不会影响之后的点)。所以实际上这是求后缀和。

    现在我们知道,对于$query(l,r)$,它等于${Xor}_{i=l-1}^{r-1}A[i]$。与原答案异或,得到$A[l-1] oplus A[r]$,若它为$1$则假,否则为真。所以我们把它看作平面上的点,对于一个$add(l,r)$操作,会对右端点在其中的产生$frac{1}{r-l+1}$的改变影响,对两端都在其中的产生$frac{2}{r-l+1}$的改变影响,对左端点在其中的产生$frac{1}{r-l+1}$的改变影响。标记合并不难。然后标记永久化一下就行了。

    对于$l=1$的单独处理。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn = 105000;
      5 
      6 const int mod = 998244353;
      7 
      8 int n,m,num=2,xL,xR,yL,yR,ans;
      9 struct qy{
     10     int cas,l,r;
     11 }Q[maxn];
     12 
     13 struct node{
     14     int ch[2],root,data;
     15 }T[maxn*300];
     16 
     17 int fast_pow(int now,int pw){
     18     int res = 1,bit = 1,fun = now;
     19     while(bit <= pw){
     20         if(bit & pw) res = (1ll*res*fun)%mod;
     21         fun = (1ll*fun*fun)%mod; bit<<=1;
     22     }
     23     return res;
     24 }
     25 
     26 int merge(int p1,int p2){return ((1ll*p1*(1-p2)+1ll*p2*(1-p1))%mod+mod)%mod;}
     27 
     28 void Query(int now,int tl,int tr,int l,int r){
     29     int pls = T[now].root,ll = tl,rr = n;
     30     while(true){
     31         int mid = (ll+rr)/2;
     32         ans = merge(ans,(1-T[pls].data+mod)%mod);
     33         if(mid >= r){
     34             if(!T[pls].ch[0]) break;
     35             else pls = T[pls].ch[0];
     36             rr = mid;
     37         }else{
     38             if(!T[pls].ch[1]) break;
     39             else pls = T[pls].ch[1];
     40             ll = mid+1;
     41         }
     42     }
     43     int mid = (tl+tr)/2;
     44     if(mid >= l){if(T[now].ch[0])Query(T[now].ch[0],tl,mid,l,r);}
     45     else{if(T[now].ch[1])Query(T[now].ch[1],mid+1,tr,l,r);}
     46 }
     47 
     48 void M2(int now,int tl,int tr,int data){
     49     if(tl >= yL && tr <= yR){
     50         T[now].data = merge(T[now].data,data);
     51         return;
     52     }
     53     int mid = (tl+tr)/2;
     54     if(!T[now].ch[0] && !T[now].ch[1]){
     55         T[now].ch[0] = ++num; T[now].ch[1] = ++num;
     56         T[num-1].data = 1; T[num].data = 1;
     57     }
     58     if(mid >= yL) M2(T[now].ch[0],tl,mid,data);
     59     if(mid < yR) M2(T[now].ch[1],mid+1,tr,data);
     60 }
     61 
     62 void Modify(int now,int tl,int tr,int data){
     63     if(tl >= xL && tr <= xR){
     64         M2(T[now].root,tl,n,data);
     65         return;
     66     }
     67     int mid = (tl+tr)/2;
     68     if(mid >= xL){
     69         if(T[now].ch[0]==0){
     70             num++;T[now].ch[0] = num;
     71             num++;T[num-1].root = num;T[num].data = 1;
     72         }
     73         Modify(T[now].ch[0],tl,mid,data);
     74     }
     75     if(mid < xR){
     76         if(T[now].ch[1]==0){
     77             num++;T[now].ch[1] = num;
     78             num++;T[num-1].root = num;T[num].data = 1;
     79         }
     80         Modify(T[now].ch[1],mid+1,tr,data);
     81     }
     82 }
     83 
     84 void read(){
     85     T[1].root = 2; T[2].data = 1;
     86     scanf("%d%d",&n,&m);
     87     for(int i=1;i<=m;i++) scanf("%d%d%d",&Q[i].cas,&Q[i].l,&Q[i].r);
     88 }
     89 
     90 void work(){
     91     int cnt = 0;
     92     for(int i=1;i<=m;i++){
     93         if(Q[i].cas == 1){
     94             cnt^=1; xL = 0,xR = Q[i].l-1,yL = Q[i].l,yR = Q[i].r;
     95             Modify(1,0,n,fast_pow(Q[i].r-Q[i].l+1,mod-2));
     96             xL = Q[i].l,xR = Q[i].r,yL = Q[i].l,yR = Q[i].r;
     97             Modify(1,0,n,2*fast_pow(Q[i].r-Q[i].l+1,mod-2)%mod);
     98             xL = Q[i].l,xR = Q[i].r,yL = Q[i].r+1,yR = n;
     99             Modify(1,0,n,fast_pow(Q[i].r-Q[i].l+1,mod-2));
    100         }else{
    101             ans = 1; Query(1,0,n,Q[i].l-1,Q[i].r);
    102             if((Q[i].l == 1 && (!cnt))||Q[i].l != 1) printf("%d
    ",ans);
    103             else printf("%d
    ",(1-ans+mod)%mod);
    104         }
    105     }
    106 }
    107 
    108 int main(){
    109     read();
    110     work();
    111     return 0;
    112 }
  • 相关阅读:
    数字形式转换
    货币转换
    温度转换
    volatile 的可见性,禁止指令重排序,无法保证原子性的理解
    mysql索引的结构的分析
    史上最详细的ORACLE19c安装说明
    Solaris 修改联网代理的设置
    Oracle Drop表并未直接删除 drop table xx purge
    oracle自定义函数创建函数索引
    连线法合并两个有序链表
  • 原文地址:https://www.cnblogs.com/Menhera/p/9277298.html
Copyright © 2011-2022 走看看