zoukankan      html  css  js  c++  java
  • 3141: [Hnoi2013]旅行

    Description

     

    Input

    第一行为两个空格隔开的正整数n, m,表示旅行的城市数与旅行所花的月数。接下来n行,其中第 i行包含两个空格隔开的整数Ai和Bi,Ai表示他第i个去的城市编号。Bi为0或1;如果Bi=0则表示城市Ai没有小L想去的景点,如果Bi=1则表示城市Ai有小L想去的景点,
    Ai两两不同且有1<=Ai<=N,即{Ai}为1,2....N的一个排列。
    例如{2,1,3,4...N}
    N<=500000,M<=200000

    Output

    t仅包括一行,包含m个空格隔开的正整数X1,X2...Xm,t仅包括一行,包含m个空格隔开的正整数X1,X2...Xm,为给小L安排的旅行计划对应的路线。为给小L安排的旅行计划对应的路线。

    Sample Input

    8 3

    2 0

    3 1

    4 1

    1 0

    5 0

    6 1

    7 1

    8 0

    Sample Output

    1 6 8

    HINT

    第1个月得到2点快乐值与2点疲劳值,第2个月得到1点快乐值与1点疲劳值,第3 个月得到1点快乐值与1点疲劳值。3个月中疲劳值与快乐值差的最大值为0,达到所有方 案最小值。

    可行方案有:

    1 6 8

    3 6 8

    3 1 8

    其中1 6 8字典序最小。

    感谢两位的题解http://www.cnblogs.com/lazycal/archive/2013/07/29/3221342.htmlhttp://cxjyxx.me/?p=329

    基本上就是他们说的了,本人愚笨,两天才刷掉它

    我就随便讲一下
    对每一个s[i]做一个单调队列
    在单调队列里维护a[i]单调递增
    当ans为0时
    每次把可以作为解的点加入单调队列,把a[i]比他小的都删掉,然后取队头
    当ans不为0时
    如果n-m+1可以做现在的解,把n-m+1这个点加进单调队列,操作一样
    为什么可以这样做,我认为是因为入队的顺序本来是按从近到远的顺序,而且都可以作为现在的解,如果a[i]比a[j]大,j在i后面,那肯定就把i删除了

      1 var
      2     s,sum,sum2,c:array[0..500010]of longint;
      3     first,tail:array[-500010..500010]of longint;
      4     next,pre,num:array[0..1000010]of longint;
      5     n,m,ans,tot,l:longint;
      6  
      7 function get(l,m:longint):longint;
      8 begin
      9     if sum[l]=0 then
     10       if sum2[l]>=m then exit(0)
     11       else exit(1)
     12     else
     13       begin
     14         get:=abs(sum[l])div m;
     15         if abs(sum[l])mod m>0 then inc(get);
     16       end;
     17 end;
     18  
     19 procedure insert(x:longint);
     20 var
     21     i:longint;
     22 begin
     23     if get(x+1,m-1)>ans then exit;
     24     inc(tot);
     25     num[tot]:=x;
     26     if first[sum[x+1]]=0 then
     27     begin
     28       first[sum[x+1]]:=tot;
     29       tail[sum[x+1]]:=tot;
     30       exit;
     31     end;
     32     i:=tail[sum[x+1]];
     33     while (i<>0)and((c[num[i]]>c[x])or(num[i]<l)) do
     34       begin
     35         if pre[i]=0 then
     36           begin
     37             i:=0;
     38             break;
     39           end;
     40         i:=pre[i];
     41       end;
     42     if i=0 then
     43     begin
     44       first[sum[x+1]]:=tot;
     45       tail[sum[x+1]]:=tot;
     46       exit;
     47     end;
     48     pre[tot]:=i;
     49     next[i]:=tot;
     50     tail[sum[x+1]]:=tot;
     51 end;
     52  
     53 procedure work2;
     54 var
     55     i,k:longint;
     56 begin
     57     l:=1;
     58     k:=1;
     59     while m>1 do
     60       begin
     61         while sum2[k]>=m-1 do
     62           begin
     63             if sum[k+1]=0 then insert(k);
     64             inc(k);
     65           end;
     66         while num[first[0]]<l do
     67           first[0]:=next[first[0]];
     68         pre[first[0]]:=0;
     69         write(c[num[first[0]]],' ');
     70         l:=num[first[0]]+1;
     71         dec(m);
     72       end;
     73     write(c[n]);
     74     halt;
     75 end;
     76  
     77 procedure init;
     78 var
     79     i:longint;
     80 begin
     81     read(n,m);
     82     for i:=1 to n do
     83       begin
     84         read(c[i],s[i]);
     85         if s[i]=0 then s[i]:=-1;
     86       end;
     87     for i:=n downto 1 do
     88       begin
     89         sum[i]:=sum[i+1]+s[i];
     90         sum2[i]:=sum2[i+1];
     91         if sum[i]=0 then inc(sum2[i]);
     92       end;
     93     ans:=get(1,m);
     94     if ans=0 then work2;
     95     for i:=1 to n-m do
     96       insert(i);
     97 end;
     98  
     99 procedure work;
    100 var
    101     i,j,min,sl,sr:longint;
    102 begin
    103     l:=1;
    104     while m>1 do
    105       begin
    106         insert(n-m+1);
    107         sl:=sum[l]-ans;
    108         sr:=ans+sum[l];
    109         j:=5000000;
    110         min:=5000000;
    111         for i:=sl to sr do
    112           begin
    113             while (first[i]<>0)and((num[first[i]]<l)or(get(num[first[i]]+1,m-1)>ans)) do
    114               first[i]:=next[first[i]];
    115             pre[first[i]]:=0;
    116             if first[i]<>0 then
    117             if c[num[first[i]]]<min then
    118             begin
    119               min:=c[num[first[i]]];
    120               j:=num[first[i]];
    121             end;
    122           end;
    123         write(min,' ');
    124         l:=j+1;
    125         dec(m);
    126       end;
    127     write(c[n]);
    128 end;
    129  
    130 begin
    131     init;
    132     work;
    133 end.
    View Code
  • 相关阅读:
    Windows10用fiddler抓包Android应用(解决手机设置代理后无法上网,设置只抓app包)
    go语言数据库操作,xorm框架
    go语言数据库操作, gorm框架
    python 多线程 及多线程通信,互斥锁,线程池
    Selenium PageFactory
    VBScript学习笔记
    4种手机自动化测试框架介绍
    Behave + Selenium(Python) ------ (第四篇)
    Behave + Selenium(Python) ------ (第三篇)
    Behave + Selenium(Python) ------ (第二篇)
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3585696.html
Copyright © 2011-2022 走看看