• P3710 方方方的数据结构


    题面

    • 如果没有撤销操作的话,它无非就是单纯的线段树。

    • 如果加上撤销操作的话,它还可以是单纯的线段树。

    • 把撤销操作看做是另一维的限制,那么修改与其对应的撤销就可以当做一个二维

      的修改。

    • 将询问的点取出来后建一棵 K-D tree 就可以当做线段树操作了。

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 #define ls son[u][0]
      4 #define rs son[u][1]
      5 #define p 998244353
      6 using namespace std;
      7 int n,m,root,K;
      8 ll tmp;
      9 ll sum[200050];
     10 ll add[200050];
     11 ll mul[200050];
     12 int t[200050],top;
     13 int opt,x[2],y[2];
     14 int L[200050][2];
     15 int R[200050][2];
     16 int val[200050][2];
     17 int son[200050][2];
     18 struct node
     19 {
     20     int opt,l,r,end;
     21     ll val;
     22 }num[200050];
     23 bool cmp(int a,int b)
     24 {
     25     return val[a][K]<val[b][K];
     26 }
     27 void pushup(int u)
     28 {
     29     add[u]=0;    mul[u]=1;
     30     for(int i=0;i<=1;++i)
     31     {
     32         L[u][i]=min(val[u][i],min(L[ls][i],L[rs][i]));
     33         R[u][i]=max(val[u][i],max(R[ls][i],R[rs][i]));
     34     }
     35 }
     36 void build(int &u,int l,int r,int k)
     37 {
     38     if(l>r)    return ;
     39     int mid=(l+r)>>1;    K=k;
     40     sort(t+l,t+r+1,cmp);
     41     u=t[mid];
     42     build(ls,l,mid-1,k^1);
     43     build(rs,mid+1,r,k^1);
     44     pushup(u);
     45 }
     46 void pushdown(int u)
     47 {
     48     if(mul[u]!=1)
     49     {
     50         (sum[ls]*=mul[u])%=p;
     51         (sum[rs]*=mul[u])%=p;
     52         (mul[ls]*=mul[u])%=p;
     53         (mul[rs]*=mul[u])%=p;
     54         (add[ls]*=mul[u])%=p;
     55         (add[rs]*=mul[u])%=p;
     56         mul[u]=1;
     57     }
     58     if(add[u]!=0)
     59     {
     60         (sum[ls]+=add[u])%=p;
     61         (sum[rs]+=add[u])%=p;
     62         (add[ls]+=add[u])%=p;
     63         (add[rs]+=add[u])%=p;
     64         add[u]=0;
     65     }
     66 }
     67 bool flagALL;
     68 bool flagALO;
     69 bool flagBIT;
     70 void check(int u)
     71 {
     72     flagALL=flagALO=flagBIT=true;
     73     for(int i=0;i<=1;++i)
     74         if(x[i]>L[u][i]||R[u][i]>y[i])
     75         {
     76             flagALL=false;
     77             if(x[i]>val[u][i]||val[u][i]>y[i])
     78             {
     79                 flagALO=false;
     80                 if(x[i]>R[u][i]||y[i]<L[u][i])
     81                     flagBIT=false;
     82             }
     83         }
     84 }
     85 void calc_add(int u)
     86 {
     87     if(!u)    return ;
     88     check(u);
     89     if(!flagBIT)
     90         return ;
     91     if(flagALO)
     92     {
     93         if(opt==1)
     94             (sum[u]+=tmp)%=p;
     95         else
     96             (sum[u]*=tmp)%=p;
     97     }
     98     if(flagALL)
     99     {
    100         if(opt==1)
    101             (add[u]+=tmp)%=p;
    102         else
    103         {
    104             (add[u]*=tmp)%=p;
    105             (mul[u]*=tmp)%=p;
    106         }
    107         return ;
    108     }
    109     pushdown(u);
    110     calc_add(ls);
    111     calc_add(rs);
    112 }
    113 void calc_ask(int u,int v)
    114 {
    115     if(!u)    return ;
    116     if(val[v][0]<L[u][0]||val[v][0]>R[u][0]||val[v][1]<L[u][1]||val[v][1]>R[u][1])
    117         return ;
    118     if(u==v)
    119     {
    120         printf("%lld
    ",sum[u]);
    121         return ;
    122     }
    123     pushdown(u);
    124     calc_ask(ls,v);
    125     calc_ask(rs,v);
    126 }
    127 int main()
    128 {
    129     //freopen("ts.in","r",stdin);
    130     //freopen("ts.out","w",stdout);
    131     scanf("%d%d",&n,&m);
    132     L[0][0]=200000;    R[0][0]=0;
    133     L[0][1]=200000;    R[0][1]=0;
    134     for(int i=1;i<=m;++i)
    135     {
    136         scanf("%d",&num[i].opt);
    137         if(num[i].opt<=2)
    138         {
    139             scanf("%d%d%lld",&num[i].l,&num[i].r,&num[i].val);
    140             num[i].end=m;
    141         }
    142         else if(num[i].opt==3)
    143         {
    144             scanf("%d",&val[i][1]);
    145             val[i][0]=i;    ++top;
    146             t[top]=i;    mul[i]=1;
    147         }
    148         else
    149         {
    150             scanf("%d",&num[i].end);
    151             num[num[i].end].end=i;
    152         }
    153     }
    154     build(root,1,top,0);
    155     for(int i=1;i<=m;++i)
    156         if(num[i].opt<=2)
    157         {
    158             opt=num[i].opt;
    159             tmp=num[i].val;
    160             tmp%=p;
    161             x[0]=i;    x[1]=num[i].l;
    162             y[0]=num[i].end;    y[1]=num[i].r;
    163             calc_add(root);
    164         }
    165         else if(num[i].opt==3)
    166             calc_ask(root,i);
    167     return 0;
    168 }
    View Code
  • 相关阅读:
    ListView自定义滑动条
    使用天天模拟器开发Android应用
    自定义对话框
    显示下载进度
    PullToRefresh的使用
    Cookie
    Servlet
    HTTP
    svn
    转:MAVEN常用命令
  • 原文地址:https://www.cnblogs.com/wyher/p/10434489.html
Copyright © 2020-2023  润新知