zoukankan      html  css  js  c++  java
  • treap

    【平衡树要是手生了就糟了、】

    Codefoces round 172 div1 E

    虽然那题是可以n^2的,但是,主要是来敲treap的所以。。

      1 #include <bits/stdc++.h>
      2 #define DB double
      3 using namespace std;
      4 const DB eps=0.00000001;
      5 int cnt,rt,x,n,t,fl; DB M,P,Q,X,w[7000],G[7000],Ans,A[1000][4];
      6 struct O{
      7     DB p,q,pp,k,b,kx,bx,x;
      8     int l,r,f;
      9 }a[30000];
     10 void ADD(int u,DB k,DB b){
     11     if (!u) return;
     12     a[u].kx+=k; a[u].k+=k;
     13     a[u].bx+=b; a[u].b+=b;
     14 }
     15 void up(int u){
     16     if (a[u].l) a[u].pp=a[a[u].l].pp;
     17     else a[u].pp=a[u].p;
     18 }
     19 void down(int u){
     20     if (!u) return;
     21     if (fabs(a[u].x)>eps){
     22         DB x=a[u].x; a[u].x=0; int v;
     23         if (v=a[u].l){
     24             a[v].pp+=x;
     25             a[v].p+=x; a[v].q+=x;
     26             a[v].b-=x*a[v].k;
     27             a[v].bx-=x*a[v].kx;
     28             a[v].x+=x;
     29         }
     30         if (v=a[u].r){
     31             a[v].pp+=x;
     32             a[v].p+=x; a[v].q+=x;
     33             a[v].b-=x*a[v].k;
     34             a[v].bx-=x*a[v].kx;
     35             a[v].x+=x;
     36         }
     37     }
     38     if (fabs(a[u].kx)>eps||fabs(a[u].bx)>eps){
     39         ADD(a[u].l,a[u].kx,a[u].bx);
     40         ADD(a[u].r,a[u].kx,a[u].bx);
     41         a[u].kx=a[u].bx=0;
     42     }
     43 }
     44 void add(int u,DB t,DB x){
     45     if (!u) return;
     46     if (a[u].pp+eps>t){
     47         a[u].pp+=x;
     48         a[u].p+=x; a[u].q+=x;
     49         a[u].b-=x*a[u].k;
     50         a[u].bx-=x*a[u].kx;
     51         a[u].x+=x; return;
     52     }
     53     down(u);
     54     if (a[u].p+eps>t){
     55         a[u].p+=x; a[u].q+=x;
     56         a[u].b-=x*a[u].k;
     57         a[u].bx-=x*a[u].kx;
     58         add(a[u].l,t,x);
     59     }
     60     add(a[u].r,t,x);
     61     up(u);
     62 }
     63 void NEW(DB p,DB q,DB k,DB b){
     64     ++t; a[t].f=(1ll*rand()*rand()+rand())%1000000000;
     65     a[t].p=a[t].pp=p; a[t].q=q;
     66     a[t].k=k; a[t].b=b;
     67 }
     68 int find(int u){
     69     down(u);
     70     if (a[u].q*a[u].k+a[u].b<-eps)
     71     if (a[u].r) return find(a[u].r); else return fl=2,u;
     72     if (a[u].p*a[u].k+a[u].b>eps)
     73     if (a[u].l) return find(a[u].l); else return fl=1,u;
     74     return u;
     75 }
     76 void RR(int &u){
     77     int v=a[u].l; down(v); a[u].l=a[v].r;
     78     a[v].r=u; up(u); up(v); u=v;
     79 }
     80 void LL(int &u){
     81     int v=a[u].r; down(v); a[u].r=a[v].l;
     82     a[v].l=u; up(u); up(v); u=v;
     83 }
     84 void del(int &u,int v){
     85     down(u);
     86     if (u==v){
     87         if (!a[u].l||!a[u].r) 
     88         u=a[u].l+a[u].r; else
     89         if (a[a[u].l].f<a[a[u].r].f)
     90             RR(u),del(a[u].r,v);
     91         else
     92             LL(u),del(a[u].l,v);
     93     }else
     94     if (a[v].p<a[u].p) del(a[u].l,v);
     95         else del(a[u].r,v);
     96     up(u);
     97 }
     98 void join(int &u,int v){
     99     if (!u) {u=v; return;}
    100     down(u);
    101     if (a[v].p<a[u].p){
    102         join(a[u].l,v); up(u);
    103         if (a[a[u].l].f<a[u].f) RR(u);
    104     }else{
    105         join(a[u].r,v); up(u);
    106         if (a[a[u].r].f<a[u].f) LL(u);
    107     }
    108 }
    109 int main(){
    110     scanf("%d%lf%lf%lf",&n,&M,&P,&Q);
    111     for (int i=1;i<=n;++i) scanf("%lf",&w[i]);
    112     rt=1; NEW(1,M,2,-2*w[1]);
    113     for (int i=2;i<=n;++i){
    114         fl=0; x=find(rt);
    115         if (fl) X=fl==1?a[x].p:a[x].q; else X=-a[x].b/a[x].k;        
    116         del(rt,x); G[i-1]=X;                    
    117         if (a[x].p<X-eps) NEW(a[x].p,X,a[x].k,a[x].b),join(rt,t);        
    118         if (X<a[x].q-eps) NEW(X,a[x].q,a[x].k,a[x].b),join(rt,t);
    119         add(rt,X,Q-P); add(rt,1,P);
    120         if (P<Q-eps) NEW(X+P,X+Q,0,0),join(rt,t);
    121         ADD(rt,2,-2*w[i]);            
    122     }
    123     fl=0; x=find(rt);
    124     if (fl) X=fl==1?a[x].p:a[x].q; else X=-a[x].b/a[x].k;
    125     G[n]=min(X,M);
    126     for (int i=n-1;i;--i){ 
    127         if (G[i]+P>G[i+1]) G[i]=G[i+1]-P;
    128         if (G[i]+Q<G[i+1]) G[i]=G[i+1]-Q;
    129     }
    130     for (int i=1;i<=n;++i) printf("%.6lf ",G[i]);
    131     for (int i=1;i<=n;++i) Ans+=(G[i]-w[i])*(G[i]-w[i]);
    132     printf("
    %.6lf
    ",Ans);
    133     return 0;
    134 }
    Steamm

    这里总结一下经验。

    ① 打标记(这里当然是针对标记下传的那种):

      线段树也一样,如果要打多种互相影响的标记,不要忘了先后顺序。

      就如线段树中最简单的,加和乘同时存在的标记一样。

        首先是一定要搞清楚 一个节点上的标记,每个标记的先后顺序。  显然 先乘法,再加法比较好。

        所以,在往一个节点附乘法标记时,要把加标记也乘上要乘的值,保持了每个节点上的标记顺序。

        在下传标记时,也要以同样的顺序下传。

      如果有些复杂的标记,想不懂如何合并(就是 加标记乘上要乘的值 那种操作),可以考虑把节点要维护的信息当成一维矩阵,比如[x,y,...,1]。

        然后,标记就变成一个二维矩阵了。(维护的信息加一个1,是为了要加常数的标记)

    ② 这里把上面的标程模板化,留下一些常用操作(可能还是有漏洞,比如要套用有reverse的题的话还得再仔细看看)。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int rt,cnt;
     4 struct O{
     5     int l,r,f;
     6 }a[30000];
     7 void up(int u){
     8     //update
     9 }
    10 void down(int u){
    11     if (!u) return;
    12     int l=a[u].l,r=a[u].r;
    13     if (a[u].tag1){
    14         if (l){
    15         }
    16         if (r){
    17         }
    18     }
    19     /*
    20     push down the tags in order
    21     */ 
    22 }
    23 int NEW(){
    24     ++cnt; a[cnt].f=(1ll*rand()*rand()+rand())%1000000000;
    25     /*
    26     initial
    27     */
    28     return cnt;
    29 }
    30 int find(int u){
    31     down(u);
    32     
    33     return u;
    34 }
    35 void RR(int &u){    //left son up
    36     int v=a[u].l; down(v); //don't forget down!
    37     a[u].l=a[v].r; a[v].r=u;
    38     up(u); up(v); u=v;
    39 }
    40 void LL(int &u){
    41     int v=a[u].r; down(v);
    42     a[u].r=a[v].l; a[v].l=u;
    43     up(u); up(v); u=v;
    44 }
    45 void del(int &u,int v){
    46     down(u);
    47     if (u==v){
    48         if (!a[u].l||!a[u].r) 
    49             u=a[u].l+a[u].r;
    50         else
    51             if (a[a[u].l].f>a[a[u].r].f)
    52                 RR(u),del(a[u].r,v);
    53             else
    54                 LL(u),del(a[u].l,v);
    55     }else
    56         if (/*in left*/) del(a[u].l,v);
    57         else del(a[u].r,v);
    58     up(u);
    59 }
    60 void join(int &u,int v){
    61     if (!u) {u=v; return;}
    62     down(u);
    63     if (/*in left*/){
    64         join(a[u].l,v); up(u);
    65         if (a[a[u].l].f>a[u].f) RR(u);
    66     }else{
    67         join(a[u].r,v); up(u);
    68         if (a[a[u].r].f>a[u].f) LL(u);
    69     }
    70 }
    71 int main(){
    72     
    73     return 0;
    74 }
    noob
  • 相关阅读:
    C语言基础
    R安装包
    随笔
    计算机组成原理(三)--存储器的层次结构
    计算机组成原理(一)
    查找
    二叉树
    Mesos
    第三章 线性表
    第四章 栈与队列
  • 原文地址:https://www.cnblogs.com/cyz666/p/7853213.html
Copyright © 2011-2022 走看看