You are on page 1of 6

Khaela Fortunela

05111940000057
PAA – B

1. SPOJ – HMLIS How Many LIS

HMLIS - HowManyLis
#binary-search

The task is simply to find LIS and number of way we can select distinct LIS
Definition :
LIS (short for Longest Increasing Subsequence) is the longest subsequence of the sequence
in which every element in the subsequence is increasing.
an LIS is distinct when one of the element come from different index of the beginning array.
this task involve finding length of Longest IS and number of way LIS can be made.

Input
First line : integer N represent number of elements in the sequence N <= 100000
Second line : N integers represent number in the sequence, each integer is in the range [1,
100000000]

Output
2 integer in 1 line, Lenght of LIS and Number of LIS that can be made.
The ans can be very large, so print both ans mod 1000000007

Example

Input:
5
1 3 2 5 4

Output:
3 4
// Explanation : the subsequence are
// (1, 3, 5), (1, 3, 4), (1, 2, 5), (1, 2, 4)

Input:
5
1 2 5 3 3

Output:
3 3
// Explanation : the subsequence are
// (1, 2, 5), (1, 2, 3), (1, 2, 3)
// note that there're two 3 in the sequence which count separately.

Last week I used dynamic programming to solve the problem above.

The code is as follows:


Khaela Fortunela
05111940000057
PAA – B

The content of array lis and count for sample input

5
1 3 2 5 4

is

1 2 2 3 3
1 1 1 2 2

To optimize the program, I tried to change the structure of the table. The table would look like this in
the end.

1 (1, 1)

2 (3, 1) (2,1)

3 (5, 2) (4,2)

I imagine above would work using two 2D vector or 2D vector of pair<int,int>.

However, since to find out the total for example row 3, we still need to iterate over (3,1) and (2,1) to
determine how many LIS ending at 5 exist. That’s why I tried this one.

1 (1, 1)

2 (3, 1) (2, 2)

3 (5, 2) (4, 4)

If for example the sequence is {1}, then we can just print 1 1.

If sequence is {1, 3}, then we can print 2 1.

If sequence is {1, 3, 2}, then we can print 2 2.

If sequence is {1, 3, 2, 5}, then we can print 3, 2.

If sequence is {1, 3, 2, 5, 4}, then we can print 3, 4.

If for example the sequence is {1, 2, 3, 5, 4, 1}, then we can insert (1,1) like below

1 (1, 1) (1, 1)

2 (3, 1) (2, 2)

3 (5, 2) (4, 4)

And the result would still be in the last row. Using sum like above makes it possible to use binary
search to optimize it. I was confused whether I should use two 2D array or vector 2Dof pair. I decide
to use vector 2D of pair. However, the solution below returned runtime error. I think traditional
array might be better in this case. The vector makes it feel more complicated.

At any row, on column 0, the sum would be the total count at the tail minus total count of left side
of found index.
Khaela Fortunela
05111940000057
PAA – B

At any row, on other than column 0, the sum would be be the total count at the tail minus total
count of left side of found index, plus the sum of previous column in a same row.

And then, at the end, we will only need to print count located in last row and last column.

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

vector<vector<pair<int, int> > > v;

int binsearch(int a, int n1, int n2){


int up = v[n1].size()-1, low=0;
while(low<=up){
int mid = (low+up)/2;
if(v[n1][mid].first<a){
low = mid+1;
}
else if(v[n1][mid].first>a){
up = mid-1;
}
}
return low;
}

pair<int,int> p;
vector<pair<int,int> > v1;

void lis_sum(int array[], int n){


p.first = array[0];
p.second = 1;
v1.push_back(p);
v.push_back(v1);
int j=0, k=0;
for (int i=1; i<n; i++) {
if(array[i] <= v[j][k].first){
k++;
p.first = array[i];
p.second = 1 + v[j][k-1].second;
v1.push_back(p);
v.push_back(v1);
}
else{
int temp = binsearch(array[i], j, k);
j++; k=0;
int s = v[j-1].size() - 1;
p.first = array[i];
p.second = v[j][k-1].second + v[j-1][s].second
- v[j-1][temp].second;
v1[].push_back(p);
v.push_back(v1);
}
}
int a=v.size()-1, b=v[a].size()-1;
printf("%d\n", v[a][b].second);
Khaela Fortunela
05111940000057
PAA – B

int main() {
int T, N;
scanf("%d", &T);
int arr[T];
for(int i=0; i<T; i++){
scanf("%d", &arr[i]);
}
lis_sum(arr, T);
return 0;
}

2. E-Olymp - 10469 Schedule


Khaela Fortunela
05111940000057
PAA – B

EXPLANATION

My strategy for this one is to use binary search with beginning upper limit is the value of r and the
lower limit 0. Because to my observation, the value of e is always smaller than r at any index. Of
course there is no need to account for negative number since e is an array of non-negative number.

By searching the minimum for each element of array r and c using binary search, I thought it would
be the solution for the program. I added the result of max(e) * k to every testing. This solution
returned right answer for the first and second example, however return 14 instead of 13 in the third
example. As of now I still haven’t find the solution for this problem. My current code is as follows.
#include <cstdio>
#include <cmath>
using namespace std;

int n, k;
int binsearch(int r, int c, int k){
int up=r, low=0;
int step=0;
while(low<up){
int mid = (up+low)/2;
int rup = abs(r-up)*c + up*k , rlow=abs(r-low)*c + low*k;

if(rup < rlow) low = mid;


else if(rup > rlow) = mid;
else {
if(abs(r-up)*c < abs(r-low)*c) up = mid;
else low = mid;
}
}
return low;
}

int main() {
scanf("%d %d\n", &n, &k);
int r[n], c[n];
Khaela Fortunela
05111940000057
PAA – B

for(int i=0; i<n; i++){


scanf("%d", &r[i]);
}
for(int i=0; i<n; i++){
scanf("%d", &c[i]);
}

int result=0, max=0;


for(int i=0; i<n; i++){
int temp = binsearch(r[i], c[i], k);
if(max<temp) max=temp;
result += abs(r[i]-temp)*c[i];
}
printf("%d\n", result + max*k);

return 0;
}

I think the code would work if I saves the previous index results and then compare it with current
element. That way the value of max(e) constantly changes during iteration of binary search.

I don’t understand what the Scoring section in the question is for.

Scoring

1. (8 балів): ci=0;
2. (15 балів): ci=1;
3. (30 балів): n≤1000;
4. (15 балів): ri≤100;
5. (32 бали): без додаткових обмежень.

You might also like