HDU 6076 Security Check(分情况DP)

来源:互联网 发布:java将xml转换成json 编辑:程序博客网 时间:2024/05/22 04:25

Security Check

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 211    Accepted Submission(s): 84


Problem Description
In airport of Bytetown, there are two long queues waiting for security check. Checking a person needs one minute, and two queues can be checked at the same time.



Picture from Wikimedia Commons


Two teams A and B are going to travel by plane. Each team has n players, ranked from 1 to n according to their average performance. No two players in the same team share the same rank. Team A is waiting in queue 1 while team B is waiting in queue 2. Nobody else is waiting for security check.

Little Q is the policeman who manages two queues. Every time he can check one person from one queue, or check one each person from both queues at the same time. He can't change the order of the queue, because that will make someone unhappy. Besides, if two players Ai and Bj are being checked at the same time, satisfying |AiBj|k, they will make a lot of noise because their rank are almost the same. Little Q should never let that happen.

Please write a program to help Little Q find the best way costing the minimum time.
 

Input
The first line of the input contains an integer T(1T15), denoting the number of test cases.

In each test case, there are 2 integers n,k(1n60000,1k10) in the first line, denoting the number of players in a team and the parameter k.

In the next line, there are n distinct integers A1,A2,...,An(1Ain), denoting the queue 1 from front to rear.

Then in the next line, there are n distinct integers B1,B2,...,Bn(1Bin), denoting the queue 2 from front to rear.
 

Output
For each test case, print a single line containing an integer, denoting the minimum time to check all people.
 

Sample Input
14 22 3 1 41 2 4 3
 

Sample Output
7
Hint
Time 1 : Check A_1.Time 2 : Check A_2.Time 3 : Check A_3.Time 4 : Check A_4 and B_1.Time 5 : Check B_2.Time 6 : Check B_3.Time 7 : Check B_4.
 

Source
2017 Multi-University Training Contest - Team 4 
 

Recommend
liuyiding

题目大意:

    有两个长度为n(1<=n<=60000)队列,每个队列中的每一个人有一个分数,每次可以从两个队伍的队首选一个检查,如果两个队队首的人分数差大于k(1<=k<=10),可以两个人同时检查,问检查完所有人最少时间。


解题思路:

    根据题意很容易想到dp[i][j]表示第一个队伍已经检查完前i个人,第二个人已经检查完前j个人所需最小时间。但是这样是O(n^2)毫无疑问会tle。我们发现k很小,所以我们可以对于两种转移方式分开处理。对于差值小于等于k的人可以普通的转移。对于差值大于k的我们可以先预处理出来每个偏移量(第一队列中选的人的位置和第二个队列中选的人的位置的差值)差值小于等于k的点对,然后通过二分找到左边最近的一个差值小于k的点,那么中间按照这个偏移量一对一对的检查,差值一定是大于k的。所以总复杂度O(n * k * log N)。


AC代码:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <ctime>#include <vector>#include <queue>#include <stack>#include <deque>#include <string>#include <map>#include <set>#include <list>using namespace std;#define INF 0x3f3f3f3f#define LL long long#define fi first#define se second#define mem(a,b) memset((a),(b),sizeof(a))const int MAXN=60010;const int MAXK=24;int N, K, a[MAXN], b[MAXN], p[MAXN];int f[MAXN][MAXK];vector<int> G[MAXN<<1];//当前偏移量,差值小于等于k的xvoid init(){    mem(f, 0);    for(int i=0;i<=(N<<1);++i)        G[i].clear();}inline bool cmp(const int &x, const int &y){    return x>y;}int dp(int x, int y){    if(!x||!y)        return x+y;    if(abs(a[x]-b[y])<=K)    {        int &g=f[x][a[x]-b[y]+K];        if(g)            return g;        return g=min(dp(x-1,y), dp(x, y-1))+1;    }    auto it=lower_bound(G[x-y+N].begin(), G[x-y+N].end(), x, cmp);    if(it==G[x-y+N].end())//当前偏移量左边没有差值小于等于t的        return max(x, y);    int t=*it;//找到可以暴力处理到的最右边的位置    return dp(t, y-x+t)+x-t;//按照当前偏移量,中间一定是可以一起检查的}int main(){    int T_T;    scanf("%d", &T_T);    while(T_T--)    {        scanf("%d%d", &N, &K);        for(int i=1;i<=N;++i)            scanf("%d", &a[i]);        for(int i=1;i<=N;++i)        {            scanf("%d", &b[i]);            p[b[i]]=i;        }        for(int i=N;i;--i)//找到所有差值不超过K的            for(int j=a[i]-K;j<=a[i]+K;++j)                if(1<=j && j<=N)                    G[i-p[j]+N].push_back(i);        printf("%d\n", dp(N, N));        init();    }        return 0;}