Round B APAC Test 2017 Problem C. Watson and Intervals

来源:互联网 发布:centos和ubuntu哪个好 编辑:程序博客网 时间:2024/05/18 03:11

Problem C. Watson and Intervals

Sherlock and Watson have mastered the intricacies of the language C++ in their programming course, so they have moved on to algorithmic problems. In today's class, the tutor introduced the problem of merging one-dimensional intervals. N intervals are given, and the ith interval is defined by the inclusive endpoints [Li, Ri], where Li ≤ Ri

The tutor defined the covered area of a set of intervals as the number of integers appearing in at least one of the intervals. (Formally, an integer p contributes to the covered area if there is some j such that Lj ≤ p ≤ Rj.) 

Now, Watson always likes to challenge Sherlock. He has asked Sherlock to remove exactly one interval such that the covered area of the remaining intervals is minimized. Help Sherlock find this minimum possible covered area, after removing exactly one of theN intervals.

Input

Each test case consists of one line with eight integers NL1, R1ABC1C2, and MN is the number of intervals, and the other seven values are parameters that you should use to generate the other intervals, as follows: 

First define x1 = L1 and y1 = R1. Then, use the recurrences below to generate xi, yi for i= 2 to N:

  • xi = ( A*xi-1 + B*yi-1 + C1 ) modulo M.
  • yi = ( A*yi-1 + B*xi-1 + C2 ) modulo M.
We define Li = min(xi, yi) and Ri = max(xi, yi), for all i = 2 to N.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the minimum possible covered area of all of the intervals remaining after removing exactly one interval.

Limits

1 ≤ T ≤ 50.
0 ≤ L1 ≤ R1 ≤ 109.
0 ≤ A ≤ 109.
0 ≤ B ≤ 109.
0 ≤ C1 ≤ 109.
0 ≤ C2 ≤ 109.
1 ≤ M ≤ 109.

Small dataset

1 ≤ N ≤ 1000.

Large dataset

1 ≤ N ≤ 5 * 105(500000).

Sample


Input 
 
Output 
 
31 1 1 1 1 1 1 13 2 5 1 2 3 4 104 3 4 3 3 8 10 10
Case #1: 0Case #2: 4Case #3: 9
In case 1, using the generation method, the set of intervals generated are: {[1, 1]}. Removing the only interval, the covered area is 0.

In case 2, using the generation method, the set of intervals generated are: {[2, 5], [3, 5], [4, 7]}. Removing the first, second or third interval would cause the covered area of remaining intervals to be 5, 6 and 4, respectively.

In case 3, using the generation method, the set of intervals generated are: {[3, 4], [1, 9], [0, 8], [2, 4]}. Removing the first, second, third or fourth interval would cause the covered area of remaining intervals to be 10, 9, 9 and 10, respectively.


Solution

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <stack>#include <list>#include <map>#include <set>#include <iterator>#include <unordered_set>#include <unordered_map>#include <algorithm>using namespace std;typedef long long ll;struct Point{    int id;    int pos;    int type;    Point() {}    Point(int id, int pos, int type): id(id), pos(pos), type(type) {}    bool operator <(const Point& p) const    {        if (pos == p.pos)            return type < p.type;        else            return pos < p.pos;    }};const int MAXN = 5e5;Point points[2*MAXN];int singleIntervals[MAXN];int main(int argc, char* argv[]){#ifndef TEST    if (argc != 2)    {        cout << "Invalid input" << endl;        return 1;    }    string input = argv[1];    string output = input.substr(0, input.length() - 2) + "out";    freopen(input.c_str(), "r", stdin);    freopen(output.c_str(), "w", stdout);#endif    int T;    int N, L1, R1, A, B, C1, C2, M;    cin >> T;    for (int i = 1; i <= T; i++)    {        cin >> N >> L1 >> R1 >> A >> B >> C1 >> C2 >> M;        points[0] = Point(0, L1, 0);        points[1] = Point(0, R1, 1);        for (int j = 1; j < N; j++)        {            int Xi, Yi;            Xi=((ll)A*L1+(ll)B*R1+C1)%M;            Yi=((ll)A*R1+(ll)B*L1+C2)%M;            points[2*j] = Point(j, min(Xi, Yi), 0);            points[2*j+1] = Point(j, max(Xi, Yi) + 1, 1);            L1 = Xi;            R1 = Yi;        }        sort(points, points + 2 * N);        int totalLen = 0, maxSingleLen = 0;        int cnt = 0, start = 0, lastEnd = 0;        memset(singleIntervals, 0, sizeof(singleIntervals));        set<int> coveredIds;        for (int j = 0; j < 2 * N; j++)        {            if (coveredIds.size() == 1)            {                int id = *(coveredIds.begin());                singleIntervals[id] += points[j].pos - lastEnd;                maxSingleLen = max(maxSingleLen, singleIntervals[id]);            }            if (points[j].type == 0)            {                coveredIds.insert(points[j].id);                if (cnt == 0)                    lastEnd = start = points[j].pos;                cnt++;            }            else            {                lastEnd = points[j].pos;                coveredIds.erase(points[j].id);                cnt--;                if (cnt == 0)                    totalLen += points[j].pos - start;            }        }        cout << "Case #" << i << ": " << totalLen - maxSingleLen << endl;    }    fclose(stdin);    fclose(stdout);    return 0;}


Note

将一条线段,拆分为2个点,左端点表示进入,右端点表示离开,在数据结构中用type表示(0表示进入,1表示离开)。然后将这些点按照规则排序(令points表示排序后的点数组),时间复杂度为O(NlogN)。

注意:

1. 对于线段、时间片段相关的题目,经常用这种方法做预处理。

2. 在我的实现中,使用了一个小的trick,两个端点使用了左闭又开的形式,即 Ri' = Ri + 1。这样做是为了便于对覆盖一个点的线段计数(令cnt表示覆盖某一个点的线段的总数)。

先来考虑如何统计所有线段覆盖的总长度?

在处理完线段重合后,当cnt为1的时候,只可能是重合线段的左端点或右端点,我们只需从左到右遍历points,找出这些点,就可以计算出总长度了,时间复杂度为O(N)。

线段之间有重合,所以本题难点在于计算出每一条线段独占的长度。换个角度考虑,就是找出只被覆盖1次的点,分别属于哪条线段。我们只要求出独占长度最长的线段,就可以得到问题的解。

同样的,在处理完线段重合后,每一个重合线段,都可以用一个set来表示这个重合线段由哪些线段组成。进一步思考,每一个重合线段上的点,也可以用一个set来表示这个点由哪些线段覆盖,set的size为1的点,即为被独占的点,此时set中唯一元素即为这个点属于的线段。这样,我们就可以计算出每一个线段的独占长度,时间复杂度为O(N)。


Reference

https://code.google.com/codejam/contest/5254487/dashboard#s=p2

0 0