• bzoj3110


    网上几乎清一色树套树,但是我就写个整体二分吧(其实是我不会树套树……)
    这题还是和原来步骤一样,二分-判定-划分,当二分答案为m的时候
    询问:大于等于m的个数大于等于k那就可能追求更大,划到右边;
    不满足意味着答案要更小,那些大于等于m的修改操作对询问影响不变,k减去他们贡献的个数,划到左边
    修改:显然大于等于m的划到右边,小于m划到左边
    两个部分内都是操作都是按时间线的顺序的
    注意这里的修改是——区间修改,区间查询……不好要上线段树?
    突然想起来树状数组也是可以解决区间求改区间查询的
    首先我们知道,区间修改时要维护一个差分数组d[i],代表[i..n]都加上d[i]
    区间修改就是对d[l]+,d[r+1]-,然后每个位置的修改总和就等于d[]的前缀和 这就是单点查询
    区间查询怎么办?我们还是想方设法变成前缀和,我们知道[l,r]=sum(r)-sum(l-1)
    而sum[x]这个前缀和又怎么求呢?我们知道sum[x]=sumpre[x](初始和)+sumdelta[x](增量和)
    重点是增量和,结合刚才的区间修改d[],我们发现,sumdelta[x]=∑d[i]*(x-i+1)=(x+1)*∑d[i]-∑d[i]*i
    然后显然我们维护两个树状数组d[i]和d[i]*i即可
    这题就解决了,没有tle,zjoi良心了一把……

    UPD:这题啊现在在bzoj上非常坑,因为加强了数据……

    转c++练模板的时候发现的,为什么不弄个hack……害得我以为c++有什么特殊之处呢……

    坑点是50000*50000爆了树状数组统计时的int,换成unsigned int就好……

    上面那个pascal程序我也顺便改了%%%(pascal范围检测比c++严格……)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stdlib.h>
      6 
      7 using namespace std;
      8 struct node{int op,l,r,k,p;} a[50010],b[50010];
      9 int q[50010],g[50010][2],c[50010],d[50010],ans[50010];
     10 bool can[50010],v[50010];
     11 int n,m,t,tot,p;
     12 
     13 int read()
     14 {
     15     int x=0,f=1;char ch=getchar();
     16     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     17     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     18     return x*f;
     19 }
     20 void work(int x,int w,int f)
     21 {
     22      for (int i=x; i<=n; i+=i&-i)
     23      {
     24          if (!v[i]) {v[i]=1; q[++tot]=i;}
     25          g[i][f]+=w;
     26      }
     27 }
     28 
     29 int ask(int x,int f)
     30 {
     31      int s=0;
     32      for (int i=x;i; i-=i&-i) s+=g[i][f];
     33      return s;
     34 }
     35 
     36 unsigned int sum(int x) //注意啊注意啊……
     37 {
     38     return (x+1)*ask(x,0)-ask(x,1);
     39 }
     40 
     41 void cdq(int l,int r,int f,int t)
     42 {
     43      if (l>r||f>t) return;
     44      int m=(l+r)>>1,h; tot=h=0;
     45      for (int i=f; i<=t; i++)
     46        if (a[i].op==1&&a[i].k>=d[m])
     47        {
     48           work(a[i].l,1,0);
     49           work(a[i].r+1,-1,0);
     50           work(a[i].l,a[i].l,1);
     51           work(a[i].r+1,-a[i].r-1,1);
     52           can[i]=1; ++h;
     53        }
     54        else if (a[i].op==2)
     55        {
     56           unsigned int s=sum(a[i].r)-sum(a[i].l-1);  
     57           if (s>=a[i].k)
     58           {
     59              ans[a[i].p]=m;
     60              can[i]=1; ++h;
     61           }
     62           else a[i].k-=s;
     63        }
     64      
     65      for (int i=1; i<=tot; i++)
     66      {
     67          int x=q[i]; v[x]=0;
     68          g[x][0]=g[x][1]=0;
     69      }
     70      int f1=f,f2=t-h+1;
     71      for (int i=f; i<=t; i++)
     72        if (can[i]) 
     73        {
     74           b[f2++]=a[i];
     75           can[i]=0;
     76        }
     77        else b[f1++]=a[i];
     78      for (int i=f; i<=t; i++)
     79        a[i]=b[i];  
     80      cdq(l,m-1,f,f1-1);
     81      cdq(m+1,r,f1,t);
     82 }  
     83      
     84 int main()
     85 {
     86     n=read(); m=read();
     87     for (int i=1;i<=m; i++)
     88     {
     89         a[i].op=read(); a[i].l=read(); a[i].r=read(); a[i].k=read();
     90         a[i].p=i;
     91         if (a[i].op==1) c[++t]=a[i].k;
     92     }
     93     sort(c+1,c+t+1);
     94     p=1; d[1]=c[1];
     95     for (int i=2;i<=t; i++)
     96       if (c[i]!=c[i-1]) d[++p]=c[i];
     97         
     98     cdq(1,p,1,m);  
     99     for (int i=1;i<=m;i++)
    100       if (ans[i]) printf("%d
    ",d[ans[i]]);
    101     return 0;
    102 }  
    c++版
      1 type node=record
      2        l,r,k,op,p:longint;
      3      end;
      4 
      5 var a,b:array[0..50010] of node;
      6     q,ans,c,g,d:array[0..50010] of longint;
      7     v1,v2:array[0..50010] of boolean;
      8     i,t,n,m,tot,p:longint;
      9 
     10 procedure swap(var a,b:longint);
     11   var c:longint;
     12   begin
     13     c:=a;
     14     a:=b;
     15     b:=c;
     16   end;
     17 
     18 procedure sort(l,r:longint);
     19   var i,j,x:longint;
     20   begin
     21     i:=l;
     22     j:=r;
     23     x:=c[(l+r) shr 1];
     24     repeat
     25       while c[i]<x do inc(i);
     26       while x<c[j] do dec(j);
     27       if not(i>j) then
     28       begin
     29         swap(c[i],c[j]);
     30         inc(i);
     31         dec(j);
     32       end;
     33     until i>j;
     34     if l<j then sort(l,j);
     35     if i<r then sort(i,r);
     36   end;
     37 
     38 function lowbit(x:longint):longint;
     39   begin
     40     exit(x and (-x));
     41   end;
     42 
     43 procedure addc(x,w:longint);
     44   begin
     45     while x<=n do
     46     begin
     47       if not v2[x] then
     48       begin
     49         v2[x]:=true;
     50         inc(tot);
     51         q[tot]:=x;
     52       end;
     53       inc(c[x],w);
     54       x:=x+lowbit(x);
     55     end;
     56   end;
     57 
     58 procedure addg(x,w:longint);
     59   begin
     60     while x<=n do
     61     begin
     62       inc(g[x],w);
     63       x:=x+lowbit(x);
     64     end;
     65   end;
     66 
     67 function askc(x:longint):longint;
     68   begin
     69     askc:=0;
     70     while x>0 do
     71     begin
     72       askc:=askc+c[x];
     73       x:=x-lowbit(x);
     74     end;
     75   end;
     76 
     77 function askg(x:longint):longint;
     78   begin
     79     askg:=0;
     80     while x>0 do
     81     begin
     82       askg:=askg+g[x];
     83       x:=x-lowbit(x);
     84     end;
     85   end;
     86 
     87 function sum(x:longint):longword;
     88   begin
     89     exit(longword(askg(x))*longword(x+1)-askc(x)); //pascal范围检测严格……
     90   end;
     91 
     92 procedure cdq(l,r,f,t:longint);
     93   var m,h,l1,l2:longint;
     94       s:longword;
     95   begin
     96     if (f>t) or (l>r) then exit;
     97     m:=(l+r) shr 1;
     98     h:=0; tot:=0;
     99     for i:=f to t do
    100       if (a[i].op=1) and (a[i].k>=d[m]) then
    101       begin
    102         addg(a[i].l,1);
    103         addg(a[i].r+1,-1);
    104         addc(a[i].l,a[i].l);
    105         addc(a[i].r+1,-a[i].r-1);
    106         v1[i]:=true; inc(h);
    107       end
    108       else if (a[i].op=2) then
    109       begin
    110         s:=sum(a[i].r)-sum(a[i].l-1);
    111         if s>=a[i].k then
    112         begin
    113           ans[a[i].p]:=m;
    114           v1[i]:=true;  inc(h);
    115         end
    116         else a[i].k:=a[i].k-s;
    117       end;
    118 
    119     for i:=1 to tot do
    120     begin
    121       c[q[i]]:=0;
    122       g[q[i]]:=0;
    123       v2[q[i]]:=false;
    124     end;
    125     l1:=f; l2:=t-h+1;
    126     for i:=f to t do
    127       if v1[i] then
    128       begin
    129         b[l2]:=a[i];
    130         inc(l2);
    131         v1[i]:=false;
    132       end
    133       else begin
    134         b[l1]:=a[i];
    135         inc(l1);
    136       end;
    137 
    138     for i:=f to t do
    139       a[i]:=b[i];
    140 
    141     cdq(l,m-1,f,l1-1);
    142     cdq(m+1,r,l1,t);
    143   end;
    144 
    145 begin
    146   readln(n,m);
    147   for i:=1 to m do
    148   begin
    149     readln(a[i].op,a[i].l,a[i].r,a[i].k);
    150     a[i].p:=i;
    151     if a[i].op=1 then
    152     begin
    153       inc(t);
    154       c[t]:=a[i].k;
    155     end;
    156   end;
    157   sort(1,t);
    158   p:=1;
    159   d[1]:=c[1];
    160   for i:=2 to t do
    161     if c[i]<>c[i-1] then
    162     begin
    163       inc(p);
    164       d[p]:=c[i];
    165     end;
    166 
    167   fillchar(c,sizeof(c),0);
    168   cdq(1,p,1,m);
    169   for i:=1 to m do
    170     if ans[i]<>0 then writeln(d[ans[i]]);
    171 end.
    pascal版
  • 相关阅读:
    Oracle(00):PL/SQL嵌入SQL语句
    Oracle(00):CASE WHEN 用法
    Oracle(00):正则表达式
    Oracle(00):删除重复记录
    Oracle(00):PL/SQL块与表达式
    Oracle(00):PL/SQL复合类型
    Oracle(00):PL/SQL数据类型
    Oracle(00):rownum行号
    Oracle(00):递归查询connect by
    Oracle(00):Update语句
  • 原文地址:https://www.cnblogs.com/phile/p/4472943.html
Copyright © 2020-2023  润新知