1. 程式人生 > >tyvj P4751 NOIP春季系列課程 H's Problem

tyvj P4751 NOIP春季系列課程 H's Problem

eve hellip one click 連續 opened 預處理 using 修改

-H‘s Problem-

描述

  小H是一個喜歡逛街的女孩子,但是由於上了大學,DDL越來越多了,她不能一直都處於逛街的狀態。為了讓自己能夠更加沈迷於學習,她規定一次逛街只逛T個單位的時間。

  小H從1號店出發,從1號店走到第i號店需要花費ai的時間,這些店形成了一條直線,也就是說小H從第i號店走到第i+1號店需要花費的時間為a{i+1}-ai。若小H選擇了第i號店並且進去逛,則會消耗bi的時間。對於第i家店,小H都對它有自己的看法。具體地,可以用ci來表示小H是否喜歡這家店。如果ci=1,則表示小H喜歡i號店,否則若ci=0,則表示小H不喜歡這家店。

  小H想盡可能逛更多的店,但是她也有屬於自己的目標,也就是說逛至少k家喜歡的店,在這個基礎上,能逛的店越多越好。

  小H現在想知道自己最多能逛多少店,當然若小H無論如何也逛不到k家喜歡的店,那麽你輸出-1就行了。

輸入格式

第一行3個數n,T,k。

接下來一行n個數表示ai。

接下來一行n個數表示bi。

接下來一行n個數表示ci。

輸出格式

輸出一個數表示答案。

輸入樣例

4 11 1

0 1 2 10

1 1 1 1

0 0 0 1

輸出樣例

1

數據範圍

對於20%的數據n<=20。

對於40%的數據n<=1000。

對於100%的數據n<=100000,1<=T<=10^9,0<=k<=n,a1=0,a1<a2<…<an<=10^9,1<=bi<=10^9,0<=ci<=1,數據有梯度。

一道蠻有趣的數據結構題;

先分析下題意,我們要求的是在 1~n 中選擇盡量多的店去逛,同時至少逛k家我們喜歡的店;

因為到每家店所需時間不同,我們走的越遠,剩余逛店時間就越少,但可選擇的店會增多,所以答案上不具備單調性,只能枚舉每一個點作為終點,然後分別求答案數;

對於任意一點 i 作為終點求答案數,實際就是在 1~i 中選擇盡量多的點,即求一個動態升序數組的前 x 項,使它們的和 <= T-a[i];

我們註意到元素的插入順序和元素大小都是已知的,因此可以通過離散化 + 排序,預處理出所有元素在數組中應在的位置,然後構建一個靜態數組,將元素按順序放進它應在的位置,這樣較動態維護快出很多;

因為數組中元素有序,所以我們求前綴和即可;

對一個動態數組進行單點修改和求前綴和,很明顯可以使用樹狀數組(當然線段樹也可);

樹狀數組中下標代表元素大小(離散化後),每個節點存儲元素個數及元素權值和(離散化前);

前綴和是連續的,因此可以對下標進行二分查找;

最後對於必須逛夠 k 家喜歡的店的問題,因為只需選擇 1~i 中前 k 家耗時最少的店,我們可以維護一個大根堆,存儲前 k 小的 k 個元素,從堆中踢出或未進堆元素則存入樹狀數組;

復雜度方面,枚舉終點 O(n),排序 + 離散化 O(n*logn),二分 + 樹狀數組查詢(修改) O(logn*logn),堆維護 O(logn),總復雜度 O(n*logn*logn);

(實際上還可以用平衡樹做,復雜度貌似可以降至 O(n*logn)

AC GET☆DAZE(大概

↓代碼(只有70分,希望dalao們能幫我挑挑錯(堆寫的很惡心orz

技術分享
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<vector>
  7 #define ll long long
  8 #define MAX_L 0x7fffffff7fffffff
  9 using namespace std;
 10 struct mk
 11 {
 12     ll c,r;
 13 };
 14 struct poi
 15 {
 16     ll n,s;
 17 };
 18 mk shop[100039];
 19 poi tree[100039]={0};
 20 ll rou[100039],tim[100039],ord[100039],hea[100039]={0},size=0,n,sum,calcs;
 21 bool kn[100039]={0};
 22 bool cmp(mk a,mk b)
 23 {
 24     return a.c<b.c;
 25 }
 26 void ueni()
 27 {
 28     ll a=size,key=hea[size];
 29     while(1)
 30     {
 31         if(tim[hea[a/2]]<tim[key])
 32         {
 33             hea[a]=hea[a/2];
 34             a/=2;
 35         }
 36         else
 37         {
 38             hea[a]=key;
 39             return;
 40         }
 41     }
 42 }
 43 void sitani()
 44 {
 45     ll a=1,key=hea[1],ne;
 46     while(1)
 47     {
 48         ne=a*2;
 49         if(tim[hea[a*2]]<tim[hea[a*2+1]])
 50         {
 51             ne++;
 52         }
 53         if(a*2>size)
 54         {
 55             hea[a]=key;
 56             return;
 57         }
 58         if(tim[hea[ne]]>tim[key])
 59         {
 60             hea[a]=hea[ne];
 61             a=ne;
 62         }
 63         else
 64         {
 65             hea[a]=key;
 66             return;
 67         }
 68     }
 69 }
 70 ll lowbit(ll k)
 71 {
 72     return -k&k;
 73 }
 74 void maketree(ll x)
 75 {
 76     ll a=ord[x];
 77     while(a<=n)
 78     {
 79         tree[a].n+=tim[x];
 80         tree[a].s++;
 81         a+=lowbit(a);
 82     }
 83     return;
 84 }
 85 ll calctree(ll x)
 86 {
 87     ll calcn=0,a=x;
 88     calcs=0;
 89     while(a)
 90     {
 91         calcn+=tree[a].n;
 92         calcs+=tree[a].s;
 93         a-=lowbit(a);
 94     }
 95     return calcn;
 96 }
 97 int main()
 98 {
 99     mk stp;
100     ll T,k,t,l,r,m,ans=-1,a,b,c;
101     scanf("%lld%lld%lld",&n,&T,&k);
102     for(a=1;a<=n;a++)
103     {
104         scanf("%lld",&rou[a]);
105     }
106     for(a=1;a<=n;a++)
107     {
108         scanf("%lld",&tim[a]);
109         stp.c=tim[a];
110         stp.r=a;
111         shop[a]=stp;
112     }
113     for(a=1;a<=n;a++)
114     {
115         scanf("%lld",&kn[a]);
116     }
117     sort(shop+1,shop+n+1,cmp);
118     for(a=1;a<=n;a++)
119     {
120         ord[shop[a].r]=a;
121     }
122     tim[0]=MAX_L;
123     for(a=1;a<=n;a++)
124     {
125         if(kn[a])
126         {
127             if(size<k)
128             {
129                 T-=tim[a];
130                 hea[++size]=a;
131                 ueni();
132             }
133             else
134             {
135                 if(hea[1]!=0 && tim[a]<tim[hea[1]])
136                 {
137                     T-=tim[a];
138                     T+=tim[hea[1]];
139                     maketree(hea[1]);
140                     hea[1]=a;
141                     sitani();
142                 }
143                 else
144                 {
145                     maketree(a);
146                 }
147             }
148         }
149         else
150         {
151             maketree(a);
152         }
153         t=T-rou[a];
154         if(size==k && t>=0)
155         {
156             l=1,r=n;
157             while(l+39<r)
158             {
159                 m=(l+r)>>1;
160                 if(calctree(m)<=t)
161                 {
162                     l=m;
163                 }
164                 else
165                 {
166                     r=m;
167                 }
168             }
169             while(calctree(l)<=t && l<=n)
170             {
171                 l++;
172                 sum=calcs;
173             }
174             ans=max(ans,sum+k);
175         }
176     }
177     printf("%lld",ans);
178     return 0;
179 }
View Code

tyvj P4751 NOIP春季系列課程 H's Problem