zoukankan      html  css  js  c++  java
  • BZOJ 3878 [AHOI&JSOI2014]奇怪的计算器 (线段树)

    题面:BZOJ传送门 洛谷传送门

    线段树好题

    题目保证$a$一定是正整数,容易发现计算结果是单调的

    我们把询问离线,并按照从小到大排序

    某次操作可能导致某些位置达到边界$L/R$

    根据单调性的结论

    这些位置一定是从$1$向右扩展或者$Q$向左扩展

    可以二分找到这个区间,然后区间覆盖

    那么修改操作,归根结底是这$4$种操作:

    1.区间加减 2.区间乘法 3.区间覆盖 4.区间每个位置加某个数*对应位置的固定权值

    比较复杂,考虑抽象化这个问题,把它写成一个函数

    $f(a,b,c)=a*f(a,b,c)+b*X_{i}+c$

    上述四种操作变成

    $1.f(1,0,x) 2.(x,0,0) 3.(0,0,x) 4.(1,x,0)$

    我们只需要每次把值往里面带,然后用线段树维护这个函数就行了

    注意下推标记的顺序 

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #define N1 100010
      5 #define ll long long 
      6 using namespace std;
      7 
      8 
      9 int gint()
     10 {
     11     int ret=0,fh=1; char c=getchar();
     12     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     13     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     14     return ret*fh;
     15 }
     16 
     17 int n;
     18 ll ml,mr;
     19 struct node{int id,x;ll ans;}q[N1];
     20 int cmp1(node s1,node s2){return s1.x<s2.x;}
     21 int cmp2(node s1,node s2){return s1.id<s2.id;}
     22 int v[N1],p[N1],f[N1],m;
     23 
     24 struct SEG{
     25 #define M1 (N1<<2)
     26 ll mi[M1],ma[M1],a[M1],b[M1],c[M1];
     27 void pushup(int rt)
     28 {
     29     mi[rt]=mi[rt<<1];             
     30     ma[rt]=ma[rt<<1|1];
     31 }
     32 void pushdown(int l,int r,int rt)
     33 {
     34     int mid=(l+r)>>1;
     35     if(a[rt]==1&&!b[rt]&&!c[rt]) return;
     36     a[rt<<1]=a[rt]*a[rt<<1];
     37     a[rt<<1|1]=a[rt]*a[rt<<1|1];
     38     b[rt<<1]=a[rt]*b[rt<<1]+b[rt]; 
     39     b[rt<<1|1]=a[rt]*b[rt<<1|1]+b[rt]; 
     40     c[rt<<1]=a[rt]*c[rt<<1]+c[rt];
     41     c[rt<<1|1]=a[rt]*c[rt<<1|1]+c[rt];
     42     mi[rt<<1]=a[rt]*mi[rt<<1]+b[rt]*v[l]+c[rt];
     43     mi[rt<<1|1]=a[rt]*mi[rt<<1|1]+b[rt]*v[mid+1]+c[rt];
     44     ma[rt<<1]=a[rt]*ma[rt<<1]+b[rt]*v[mid]+c[rt];
     45     ma[rt<<1|1]=a[rt]*ma[rt<<1|1]+b[rt]*v[r]+c[rt];
     46     a[rt]=1; b[rt]=c[rt]=0;
     47 }
     48 void update(int L,int R,int l,int r,int rt,ll A,ll B,ll C)
     49 {
     50     if(L<=l&&r<=R) 
     51     {
     52         a[rt]=A*a[rt];
     53         b[rt]=A*b[rt]+B;  
     54         c[rt]=A*c[rt]+C;
     55         mi[rt]=A*mi[rt]+B*v[l]+C;
     56         ma[rt]=A*ma[rt]+B*v[r]+C;
     57         return;
     58     }
     59     int mid=(l+r)>>1;
     60     if(L<=mid) update(L,R,l,mid,rt<<1,A,B,C);
     61     if(R>mid) update(L,R,mid+1,r,rt<<1|1,A,B,C);
     62     pushup(rt);
     63 
     64 }
     65 ll calc1(int x,ll rt,ll A,ll B,ll C){return A*mi[rt]+B*v[x]+C;}
     66 ll calc2(int x,ll rt,ll A,ll B,ll C){return A*ma[rt]+B*v[x]+C;}
     67 ll de;
     68 int qleft(int l,int r,int rt,int A,int B,int C)
     69 {
     70     if(l==r){ if(calc2(r,rt,A,B,C)>ml) return l-1; return l; }
     71     int mid=(l+r)>>1; pushdown(l,r,rt); de=calc2(mid,rt<<1,A,B,C);
     72     if(calc2(mid,rt<<1,A,B,C)<=ml) return qleft(mid+1,r,rt<<1|1,A,B,C);
     73     else return qleft(l,mid,rt<<1,A,B,C);
     74 }
     75 int qright(int l,int r,int rt,int A,int B,int C)
     76 {
     77     if(l==r){ if(calc1(l,rt,A,B,C)<mr) return l+1; return l; }
     78     int mid=(l+r)>>1; pushdown(l,r,rt); de=calc1(mid+1,rt<<1|1,A,B,C);
     79     if(calc1(mid+1,rt<<1|1,A,B,C)>=mr) return qright(l,mid,rt<<1,A,B,C);
     80     else return qright(mid+1,r,rt<<1|1,A,B,C);
     81 }
     82 void build(int l,int r,int rt)
     83 {
     84     a[rt]=1; b[rt]=c[rt]=0;
     85     if(l==r){ mi[rt]=ma[rt]=v[l]; return; }
     86     int mid=(l+r)>>1;
     87     build(l,mid,rt<<1);
     88     build(mid+1,r,rt<<1|1);
     89     pushup(rt);
     90 }
     91 void print(int l,int r,int rt,node *s)
     92 {
     93     if(l==r){ s[l].ans=mi[rt]; return; }
     94     int mid=(l+r)>>1; pushdown(l,r,rt);
     95     print(l,mid,rt<<1,s); 
     96     print(mid+1,r,rt<<1|1,s);
     97 }
     98 ll query(int x,int l,int r,int rt)
     99 {
    100     if(l==r) return mi[rt];
    101     int mid=(l+r)>>1; pushdown(l,r,rt);
    102     if(x<=mid) return query(x,l,mid,rt<<1);
    103     else return query(x,mid+1,r,rt<<1|1);
    104 }
    105 }s;
    106 
    107 
    108 int main()
    109 {
    110     scanf("%d%lld%lld",&n,&ml,&mr);
    111     char str[10]; int i,j,l,r;
    112     for(i=1;i<=n;i++) 
    113     {
    114         scanf("%s",str);
    115         switch(str[0])
    116         {
    117             case '+': p[i]=1; break;
    118             case '-': p[i]=2; break;
    119             case '*': p[i]=3; break;
    120             case '@': p[i]=4; break;
    121         }
    122         f[i]=gint();
    123     }
    124     scanf("%d",&m);
    125     for(i=1;i<=m;i++) q[i].x=gint(),q[i].id=i;
    126     sort(q+1,q+m+1,cmp1);
    127     for(i=1;i<=m;i++) v[i]=q[i].x;
    128     s.build(1,m,1);
    129     s.query(1,1,m,1);
    130     for(i=1;i<=n;i++)
    131     {
    132         switch(p[i])
    133         {
    134         
    135         case 1:
    136         { 
    137             l=s.qright(1,m,1,1,0,f[i]),r=m;
    138             if(l>1) s.update(1,l-1,1,m,1,1,0,f[i]); 
    139             if(l<=r) s.update(l,r,1,m,1,0,0,mr); 
    140             break;
    141         }
    142         case 2: 
    143         {
    144             l=s.qleft(1,m,1,1,0,-f[i]),r=m;
    145             if(l>0) s.update(1,l,1,m,1,0,0,ml);
    146             if(l<r) s.update(l+1,r,1,m,1,1,0,-f[i]); 
    147             break;
    148         }
    149         case 3: 
    150         {
    151             l=s.qright(1,m,1,f[i],0,0),r=m;
    152             if(l>1) s.update(1,l-1,1,m,1,f[i],0,0); 
    153             if(l<=r) s.update(l,r,1,m,1,0,0,mr); 
    154             break;
    155         }
    156         case 4: 
    157         {
    158             l=s.qright(1,m,1,1,f[i],0),r=m;
    159             if(l>1) s.update(1,l-1,1,m,1,1,f[i],0); 
    160             if(l<=r) s.update(l,r,1,m,1,0,0,mr);
    161             break;
    162         }
    163         
    164         }
    165         
    166     }
    167     s.print(1,m,1,q);
    168     sort(q+1,q+m+1,cmp2);
    169     for(i=1;i<=m;i++) printf("%lld
    ",q[i].ans);
    170     return 0;
    171 }
  • 相关阅读:
    LOJ6395 「THUPC2018」城市地铁规划 / City
    [题解] 好好
    [题解] CF1316F Battalion Strength
    【题解】CF1320D Reachable Strings
    【题解】夕张的改造
    【题解】期望次数
    [FJWC2020] lg
    Django 多表操作
    Django 单表操作
    Django 模板层 静态文件
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10326241.html
Copyright © 2011-2022 走看看