1314: River过河
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 26 Solved: 10
[Submit][Status][Discuss]
Description
ZY
带N个小Kid过河,小KID分成两种:高一年级,高二年级,由于存在代沟问题,如果同一条船上高一年级生和高二年级生数量之差超过K,就会发生不和谐的
事件.当然如果一条船上全是同一年级的,就绝对不会发生争执.现在ZY按小KID队列的顺序依次安排上船,并且不能让他们在过河时发生争执.对于当前等待
上船的小KID来说,要么让他上船,要么将停在渡口的船开走,再让他上另一条船,同一条船上的人不过超过M人.为了让所有的小KID过河,在知悉小KID
队列的情况下,最少需要多少条船.
Input
第一行给出N,M,K.含义如上所述
下行N行用来描述小KID的队列,每行一个字符”A”或者”L”
Output
最少需要多少条船
Sample Input
5 4 1
A
L
L
L
A
A
L
L
L
A
Sample Output
2
HINT
前三个人一条船,后两个人一条船
数据范围
30% 数据中1<=N<=1000
100%数据中1<=N<=250000,1<=M,K<=N
这道题过的人这么少不太正常啊。
容易看出,如果对输入数列换成+1/-1,然后做前缀和,当前dp[i]可以由j-i>=m and abs(a[j]-a[i])<=k 一个矩形内区域的dp值转移出来,首先kdtree肯定没有问题,看有无简单点的做法,思考整体二分,发现不太好处理,注意上述的矩形区域有着固定的宽,而且x坐标单调递增,于是很容易想到对于每一个a[i]维护优先队列了。
用deque<int>要mle,原因是deque封装了大量维护下标访问的量,而改成list<int>内存要好很多。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<deque> #include<list> using namespace std; #define MAXN 251000 #define lch (now<<1) #define rch (now<<1^1) #define smid ((l+r)>>1) #define MAXT MAXN*4 #define INF 0x3f3f3f3f int a[MAXN]; int dp[MAXN]; list<int> lst[MAXN]; int sgt[MAXT]; void Modify_sgt(int now,int l,int r,int pos,int v) { if (l==r) { sgt[now]=v; return ; } if (pos<=smid) Modify_sgt(lch,l,smid,pos,v); else Modify_sgt(rch,smid+1,r,pos,v); sgt[now]=min(sgt[lch],sgt[rch]); } int Query_sgt(int now,int l,int r,int x,int y) { if (l==x && r==y) return sgt[now]; if (y<=smid) return Query_sgt(lch,l,smid,x,y); else if (smid<x) return Query_sgt(rch,smid+1,r,x,y); else return min(Query_sgt(lch,l,smid,x,smid),Query_sgt(rch,smid+1,r,smid+1,y)); } list<int> que; int main() { freopen("input.txt","r",stdin); int n,m,t,x,y,z; scanf("%d%d%d ",&n,&m,&t); char ch; int level=0; int mxvvv=0; memset(sgt,INF,sizeof(sgt)); a[0]=0; for (int i=1;i<=n;i++) { scanf("%c ",&ch); if (ch=='A') a[i]=1; else a[i]=-1; } for (int i=1;i<=n;i++) a[i]+=a[i-1]; for (int i=0;i<=n;i++) level=min(a[i],level); for (int i=0;i<=n;i++) mxvvv=max(a[i],mxvvv); level=-level; mxvvv+=level; for (int i=0;i<=n;i++) a[i]+=level; dp[0]=0; lst[a[0]].push_back(0); Modify_sgt(1,0,mxvvv,a[0],dp[lst[a[0]].front()]); que.push_back(1); for (int i=1;i<=n;i++) { dp[i]=Query_sgt(1,0,mxvvv,max(0,a[i]-t),min(mxvvv,a[i]+t))+1; if (que.size() && a[que.front()]-a[que.front()-1]==a[i]-a[i-1]) dp[i]=min(dp[i],dp[que.front()-1]+1); while (lst[a[i]].size() && dp[lst[a[i]].back()]>=dp[i]) lst[a[i]].pop_back(); lst[a[i]].push_back(i); Modify_sgt(1,0,mxvvv,a[i],dp[lst[a[i]].front()]); if (i>=m) { if (lst[a[i-m]].size() && lst[a[i-m]].front()==i-m) { lst[a[i-m]].pop_front(); if (lst[a[i-m]].size()) Modify_sgt(1,0,mxvvv,a[i-m],dp[lst[a[i-m]].front()]); else Modify_sgt(1,0,mxvvv,a[i-m],INF); } } if (i==1 || a[i]-a[i-1]==a[i+1]-a[i]) { while (!que.empty() && dp[que.back()-1]>=dp[i]) que.pop_back(); que.push_back(i+1); }else { while (!que.empty()) que.pop_back(); que.push_back(i+1); } if (i-que.front()+1>=m) que.pop_front(); } printf("%d ",dp[n]); }