• bzoj 4821 [Sdoi2017]相关分析


    题面

    https://www.lydsy.com/JudgeOnline/problem.php?id=4821

    题解

    做法显然 就是维护一颗线段树

    里面装4个东西 区间x的和 区间y的和 区间$x^2$的和 区间$xy$的和

    然后装4个标记 add操作对x的影响 add操作对y的影响 cover操作对x的影响 cover操作对y的影响

    唯一要想一想的东西在于怎么维护顺序

    我一开始的愚蠢做法是每个节点维护一个nw nw=0表示当前节点上一次受到的操作是add nw=1表示....是cover

    然后每次pushdown的时候 例如当前节点的nw是0 现在我们把它pushdown 我们看左儿子 如果他的nw是1 我们就得先pushdown它的左儿子 然后在更新左儿子的值 右儿子类似

    如果当前节点的nw是1 也就是cover操作 就不需要管左儿子和右儿子的nw 因为全都被cover掉了

    这样复杂度是

    事实上这样写很麻烦

    我们不需要维护nw 因为cover操作的特殊性: cover之后就不用管之前干了什么

    那么对于一个节点 如果tag1,tag2不为0 且tag3,tag4也不为0 那么我们先做tag3,tag4也就是先cover

    每次cover操作的时候我们把节点的tag1,tag2设为0,也就是之前的操作全不管

    这样复杂度少一个log 而且好写一些

    Code

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 
      5 ll read(){
      6     ll x=0,f=1;char c=getchar();
      7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
      8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
      9     return x*f;
     10 }
     11 
     12 struct Node{
     13     int l,r;
     14     long double x,y,xy,x2;
     15     long double tag1,tag2,tag3,tag4;
     16     //如果tag1,tag3同时有值,表示先算cover操作(tag3,tag4)再算add操作(tag1,tag2)
     17     Node(){
     18         x=y=xy=x2=0;
     19     }
     20 
     21     void pr(){
     22         cout<<x<<' '<<y<<' '<<xy<<' '<<x2<<endl;
     23     }
     24 } tr[400400];
     25 
     26 #define lc (i<<1)
     27 #define rc (i<<1|1)
     28 ll x[100100],y[100100];
     29 
     30 inline long double calc_sum(int l,int r){
     31     return (long double)(r-l+1)*(l+r)/2;
     32 }
     33 inline long double calc_sqr(int l){
     34     return (long double)l*(l+1)*(2*l+1)/6;
     35 }
     36 inline long double calc_sqr(int l,int r){
     37     return calc_sqr(r)-calc_sqr(l-1);
     38 }
     39 
     40 void update(int i){
     41     tr[i].x=tr[lc].x+tr[rc].x;
     42     tr[i].y=tr[lc].y+tr[rc].y;
     43     tr[i].xy=tr[lc].xy+tr[rc].xy;
     44     tr[i].x2=tr[lc].x2+tr[rc].x2;
     45 }
     46 
     47 void build(int i,int l,int r){
     48     tr[i].l=l,tr[i].r=r;
     49     if(l==r){
     50         tr[i].x=x[l],tr[i].y=y[l];
     51         tr[i].x2=(long double)x[l]*x[l],tr[i].xy=(long double)x[l]*y[l];
     52         return;
     53     }
     54     int md=(l+r)>>1;
     55     build(lc,l,md),build(rc,md+1,r);
     56     update(i);
     57 }
     58 
     59 void CHANGE(int i,long double s,long double t){
     60     tr[i].tag3=s,tr[i].tag4=t;
     61     tr[i].tag1=tr[i].tag2=0;
     62     int len=tr[i].r-tr[i].l+1;
     63     tr[i].x=calc_sum(s+tr[i].l,s+tr[i].r);
     64     tr[i].y=calc_sum(t+tr[i].l,t+tr[i].r);
     65     tr[i].x2=calc_sqr(s+tr[i].l,s+tr[i].r);
     66     tr[i].xy=s*t*len+calc_sum(tr[i].l,tr[i].r)*t+calc_sum(tr[i].l,tr[i].r)*s+calc_sqr(tr[i].l,tr[i].r);
     67 }
     68 
     69 void pushdown2(int i){
     70     long double s=tr[i].tag3,t=tr[i].tag4;
     71     CHANGE(lc,s,t);
     72     CHANGE(rc,s,t);
     73     tr[i].tag3=tr[i].tag4=0;
     74 }
     75 
     76 void change(int i,long double s,long double t){
     77     tr[i].tag1+=s,tr[i].tag2+=t;
     78     int len=tr[i].r-tr[i].l+1;
     79     tr[i].x2+=2*tr[i].x*s+s*s*len;
     80     tr[i].xy+=tr[i].x*t+tr[i].y*s+s*t*len;
     81     tr[i].x+=s*len;
     82     tr[i].y+=t*len;
     83 }
     84 
     85 void pushdown1(int i){
     86     long double s=tr[i].tag1,t=tr[i].tag2;
     87     change(lc,s,t);
     88     change(rc,s,t);
     89     tr[i].tag1=tr[i].tag2=0;
     90 }
     91 
     92 void pushdown(int i){
     93     if(tr[i].tag3!=0 || tr[i].tag4!=0){
     94         pushdown2(i);
     95     }
     96     if(tr[i].tag1!=0 || tr[i].tag2!=0){
     97         pushdown1(i);
     98     }
     99 }
    100 
    101 void change1(int i,int l,int r,int s,int t){
    102     if(tr[i].l>r || tr[i].r<l) return;
    103     if(tr[i].l>=l && tr[i].r<=r){
    104         change(i,s,t);
    105         return;
    106     }
    107     pushdown(i);
    108     change1(lc,l,r,s,t);
    109     change1(rc,l,r,s,t);
    110     update(i);
    111 }
    112 
    113 void change2(int i,int l,int r,int s,int t){
    114     if(tr[i].l>r || tr[i].r<l) return;
    115     if(tr[i].l>=l && tr[i].r<=r){
    116         CHANGE(i,s,t);
    117         return;
    118     }
    119     pushdown(i);
    120     change2(lc,l,r,s,t);
    121     change2(rc,l,r,s,t);
    122     update(i);
    123 }
    124 
    125 Node query(int i,int l,int r){
    126     Node ret;
    127     if(tr[i].l>r || tr[i].r<l) return ret;
    128     if(tr[i].l>=l && tr[i].r<=r) return tr[i];
    129     pushdown(i);
    130     Node n1,n2;
    131     n1=query(lc,l,r);
    132     n2=query(rc,l,r);
    133     ret.x=n1.x+n2.x;ret.y=n1.y+n2.y;ret.xy=n1.xy+n2.xy;ret.x2=n1.x2+n2.x2;
    134     return ret;
    135 }
    136 
    137 void ask(int l,int r){
    138     int len=r-l+1;
    139     Node nw=query(1,l,r);
    140     //nw.pr();
    141     long double xba=nw.x*1.0/len,yba=nw.y*1.0/len;
    142     long double fz=nw.xy-nw.y*xba-nw.x*yba+xba*yba*len;
    143     long double fm=nw.x2-2*nw.x*xba+xba*xba*len;
    144     printf("%.10Lf
    ",fz/fm);
    145 }
    146 
    147 int n,m;
    148 
    149 int main(){
    150     #ifdef LZT
    151     freopen("in","r",stdin);
    152     #endif
    153     n=read(),m=read();
    154     for(int i=1;i<=n;i++) x[i]=read();
    155     for(int i=1;i<=n;i++) y[i]=read();
    156     build(1,1,n);
    157     while(m--){
    158         int tp=read();
    159         if(tp==1){
    160             int l=read(),r=read();
    161             ask(l,r);
    162         }
    163         else if(tp==2){
    164             int l=read(),r=read(),s=read(),t=read();
    165             change1(1,l,r,s,t);
    166         }
    167         else if(tp==3){
    168             int l=read(),r=read(),s=read(),t=read();
    169             change2(1,l,r,s,t);
    170         }
    171     }
    172     return 0;
    173 }
    174 
    175 /*
    176 3 5
    177 1 2 3
    178 1 2 3
    179 1 1 3
    180 2 2 3 -3 2
    181 1 1 2
    182 3 1 2 2 1
    183 1 1 3
    184 */
    View Code

    Review

    都得开long double

    一开始只开了long long 爆炸 调了半天

  • 相关阅读:
    (三)索引分区知识详解
    (二)SQL Server分区创建过程
    (一)SQL Server分区详解Partition(目录)
    表格重新加载 where 携带上次值问题
    MongoDB 时差问题问题
    WebAPI跨域处理
    Http请求中 content-type 和 dataType 区别
    那些坑
    微信公众平台开发系列一 ~ 接入前的配置工作
    MVC中登录页图片验证码总结
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9357262.html
Copyright © 2020-2023  润新知