zoukankan      html  css  js  c++  java
  • 【BZOJ2527】Meteors(整体二分)

    题意:

    Byteotian Interstellar Union有N个成员国。现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站。
    这个星球经常会下陨石雨。BIU已经预测了接下来K场陨石雨的情况。
    BIU的第i个成员国希望能够收集Pi单位的陨石样本。你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石。
    输入:
    第一行是两个数N,M。
    第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站。
    第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量。
    第四行有一个数K,表示BIU预测了接下来的K场陨石雨。
    接下来K行,每行有三个数Li,Ri,Ai,表示第K场陨石雨的发生地点在从Li顺时针到Ri的区间中(如果Li<=Ri,就是Li,Li+1,...,Ri,否则就是Ri,Ri+1,...,m-1,m,1,...,Li),向区间中的每个太空站提供Ai单位的陨石样本。
    输出:
    N行。第i行的数Wi表示第i个国家在第Wi波陨石雨之后能够收集到足够的陨石样本。如果到第K波结束后仍然收集不到,输出NIE。
    数据范围: 1<=n,m,k<=3*10^5 1<=Pi<=10^9 1<=Ai<10^9
     
    思路:RYZ作业
    整体二分很显然,卡了5-6天,线段树标记持久化都过不去,树状数组暴力清空也T,实在是没办法了……
      1 var s1,s2:array[1..400000]of extended;
      2     t:array[1..400000]of longint;
      3     c,q:array[1..710000]of record
      4                              l,r,op,t:longint;
      5                              a:int64;
      6                              s:extended;
      7                             end;
      8     b:array[1..710000]of extended;
      9     head,vet,next,ans,flag:array[1..710000]of longint;
     10     n,m,i,k,tot,x,time:longint;
     11  
     12 procedure add(x:longint;y:extended);
     13 var i:longint;
     14 begin
     15  i:=x;
     16  while i<=m do
     17  begin
     18   if t[i]<>time then
     19   begin
     20    s1[i]:=0; s2[i]:=0; t[i]:=time;
     21   end;
     22   s1[i]:=s1[i]+y;
     23   s2[i]:=s2[i]+y*x;
     24   i:=i+i and (-i);
     25  end;
     26 end;
     27  
     28 function query(x:longint):extended;
     29 var i:longint;
     30 begin
     31  query:=0; i:=x;
     32  while i>0 do
     33  begin
     34   if t[i]=time then query:=query+s1[i]*(x+1)-s2[i];
     35   i:=i-i and (-i);
     36  end;
     37 end;
     38  
     39 procedure solve(x,y,l,r:longint);
     40 var i,j,mid,pre,now,u,e,v:longint;
     41     tmp:extended;
     42 begin
     43  if l>r then exit;
     44  if l=r then
     45  begin
     46   for i:=x to y do
     47    if c[i].op=2 then ans[c[i].a]:=l;
     48   exit;
     49  end;
     50  mid:=(l+r)>>1;
     51  pre:=x; now:=x; inc(time);
     52  for i:=x to y do
     53   if c[i].op=1 then
     54   begin
     55    if c[i].t<=mid then
     56    begin
     57     if c[i].l>c[i].r then
     58     begin
     59      add(c[i].l,c[i].a);
     60      add(1,c[i].a);
     61      add(c[i].r+1,-c[i].a);
     62     end
     63      else
     64      begin
     65       add(c[i].l,c[i].a);
     66       add(c[i].r+1,-c[i].a);
     67      end;
     68     flag[i]:=0;
     69     inc(now);
     70    end
     71     else flag[i]:=1;
     72   end;
     73  for i:=x to y do
     74   if c[i].op=2 then
     75   begin
     76    u:=c[i].a; tmp:=0;
     77    e:=head[u];
     78    while e<>0 do
     79    begin
     80     v:=vet[e];
     81     tmp:=tmp+query(v)-query(v-1);
     82     if tmp>=c[i].s then break;
     83     e:=next[e];
     84    end;
     85    if tmp>=c[i].s then
     86    begin
     87     inc(now); flag[i]:=0;
     88    end
     89     else
     90     begin
     91      flag[i]:=1; c[i].s:=c[i].s-tmp;
     92     end;
     93   end;
     94   
     95  for i:=x to y do
     96   if flag[i]=1 then
     97   begin
     98    q[now]:=c[i]; inc(now);
     99   end
    100    else
    101    begin
    102     q[pre]:=c[i]; inc(pre);
    103    end;
    104  for i:=x to y do c[i]:=q[i];
    105  solve(x,pre-1,l,mid);
    106  solve(pre,y,mid+1,r);
    107 end;
    108  
    109 procedure add(a,b:longint);
    110 begin
    111  inc(tot);
    112  next[tot]:=head[a];
    113  vet[tot]:=b;
    114  head[a]:=tot;
    115 end;
    116  
    117 begin
    118  
    119  read(n,m);
    120  for i:=1 to m do
    121  begin
    122   read(x);
    123   add(x,i);
    124  end;
    125  for i:=1 to n do read(b[i]);
    126  read(k);
    127  for i:=1 to k do
    128  begin
    129   read(c[i].l,c[i].r,c[i].a);
    130   c[i].op:=1; c[i].t:=i;
    131  end;
    132  for i:=1 to n do
    133  begin
    134   c[i+k].op:=2;
    135   c[i+k].a:=i; c[i+k].s:=b[i];
    136  end;
    137  
    138  solve(1,k+n,1,k+1);
    139  for i:=1 to n do
    140   if ans[i]<=k then writeln(ans[i])
    141    else writeln('NIE');
    142  
    143 end.
     
  • 相关阅读:
    【2021-01-26】保持学习,也是一种科学的健康保养方式
    【2021-01-25】正常市场化的企业该有的现象
    day 42 mysql 数据库(2)
    day 41 数据库初学习
    在排序数组中查找元素的第一个和最后一个位置
    飞机游戏
    两个数组的交集 II
    重复N次的元素
    单词规律
    存在重复元素2
  • 原文地址:https://www.cnblogs.com/myx12345/p/6586774.html
Copyright © 2011-2022 走看看