/*************************************************************************
* Zadanie: Druzny *
* Zlozonosc czasowa: O(n^2 log n) *
* Wynik: --/10 *
*************************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define SIZE(c) (int) (c).size()
#define FOREACH(i,c) FOR(i,0,SIZE(c)-1)
#define FORDEACH(i,c) FORD(i,SIZE(c)-1,0)
#define MIN(x,y) ( ((x) < (y))? (x) : (y) )
#define MAX(x,y) ( ((x) > (y))? (x) : (y) )
#define PB push_back
#define INF 2000000
#define MOD 1000000007
#define par(x) ( (x-1)/2 )
using namespace std;
int F(int x, int y, int t)
{
if (t) return MIN(x,y);
else return MAX(x,y);
}
int p = 1;
vector < int > T[2]; //drzewo minimow i maximow
int Query(int l, int r, bool t) //0 - max, 1 - min
{
l += p-1;
r += p-1;
int ans = F(T[t][l],T[t][r],t);
while (par(l) != par(r))
{
if (l%2 == 1) ans = F(ans,T[t][l+1],t);
if (r%2 == 0) ans = F(ans,T[t][r-1],t);
l = par(l);
r = par(r);
}
return ans;
}
bool IsGood(int l, int r)//czy przedzial [l,r] tworzy druzyne
{
int c = Query(l,r,0), d = Query(l,r,1), k = r - l + 1;
return ((k >= c) && (k <= d));
}
/*************************************************************************/
int main()
{
ios_base::sync_with_stdio(0);
int n;
cin >> n;
while (p < n) p *= 2;
T[0].resize(2*p-1,0);
T[1].resize(2*p-1,INF);
FOR(i,p-1,p+n-2) FOR(j,0,1)
cin >> T[j][i];
FORD(i,p-2,0) FOR(j,0,1)
T[j][i] = F(T[j][2*i+1],T[j][2*i+2],j);
vector < int > D(n,0);
vector < int > cnt(n,0);
FOREACH(i,D)
{
int left = MAX(0,i+1-T[1][i+p-1]), right = MAX(0,i+1-T[0][i+p-1]);
FOR(j,left,right) if(IsGood(j,i) && (j == 0 || D[j-1] > 0))
{
int num = 1 + ((j == 0)? 0 : D[j-1]);
if (num > D[i])
{
D[i] = num;
cnt[i] = ((j == 0)? 1 : cnt[j-1]);
}
else if (num == D[i])
cnt[i] = (cnt[i] + cnt[j])%MOD;
}
}
if (D[n-1] == 0)
cout << "NIE";
else
cout << D[n-1] << ' ' << cnt[n-1];
return 0;
}
/*************************************************************************/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | /************************************************************************* * Zadanie: Druzny * * Zlozonosc czasowa: O(n^2 log n) * * Wynik: --/10 * *************************************************************************/ #include <iostream> #include <vector> #include <algorithm> #define FOR(i,b,e) for(int i=(b); i <= (e); ++i) #define FORD(i,b,e) for(int i=(b); i >= (e); --i) #define SIZE(c) (int) (c).size() #define FOREACH(i,c) FOR(i,0,SIZE(c)-1) #define FORDEACH(i,c) FORD(i,SIZE(c)-1,0) #define MIN(x,y) ( ((x) < (y))? (x) : (y) ) #define MAX(x,y) ( ((x) > (y))? (x) : (y) ) #define PB push_back #define INF 2000000 #define MOD 1000000007 #define par(x) ( (x-1)/2 ) using namespace std; int F(int x, int y, int t) { if (t) return MIN(x,y); else return MAX(x,y); } int p = 1; vector < int > T[2]; //drzewo minimow i maximow int Query(int l, int r, bool t) //0 - max, 1 - min { l += p-1; r += p-1; int ans = F(T[t][l],T[t][r],t); while (par(l) != par(r)) { if (l%2 == 1) ans = F(ans,T[t][l+1],t); if (r%2 == 0) ans = F(ans,T[t][r-1],t); l = par(l); r = par(r); } return ans; } bool IsGood(int l, int r)//czy przedzial [l,r] tworzy druzyne { int c = Query(l,r,0), d = Query(l,r,1), k = r - l + 1; return ((k >= c) && (k <= d)); } /*************************************************************************/ int main() { ios_base::sync_with_stdio(0); int n; cin >> n; while (p < n) p *= 2; T[0].resize(2*p-1,0); T[1].resize(2*p-1,INF); FOR(i,p-1,p+n-2) FOR(j,0,1) cin >> T[j][i]; FORD(i,p-2,0) FOR(j,0,1) T[j][i] = F(T[j][2*i+1],T[j][2*i+2],j); vector < int > D(n,0); vector < int > cnt(n,0); FOREACH(i,D) { int left = MAX(0,i+1-T[1][i+p-1]), right = MAX(0,i+1-T[0][i+p-1]); FOR(j,left,right) if(IsGood(j,i) && (j == 0 || D[j-1] > 0)) { int num = 1 + ((j == 0)? 0 : D[j-1]); if (num > D[i]) { D[i] = num; cnt[i] = ((j == 0)? 1 : cnt[j-1]); } else if (num == D[i]) cnt[i] = (cnt[i] + cnt[j])%MOD; } } if (D[n-1] == 0) cout << "NIE"; else cout << D[n-1] << ' ' << cnt[n-1]; return 0; } /*************************************************************************/ |
English