PROBLEM LINK:
Contest Division 1
Contest Division 2
Contest Division 3
Contest Division 4
Setter: Aditya Mittal
Tester: Satyam, Jatin Garg
Editorialist: Devendra Singh
DIFFICULTY:
2179
PREREQUISITES:
PROBLEM:
Chef has a garden of size N \times N. The garden is divided into N^2 squares of size 1\times 1 each.
Chef has plants in some unit squares of the garden, because of which, that part looks green.
Formally, for the i^{th} row (0 \le i \lt N), Chef has plants in all the columns from A_i to B_i (both inclusive) where 0 \le A_i \le B_i \lt N.
Help Chef find the length of the side of the largest square that is green.
EXPLANATION:
Observation : If there exists a square of side length L that is green, then there exists a square of side length L-1 that is green too. To prove this, just cut the square of side L-1 from the square of side length L (that is green) from the top left corner of it.
This observation suggests that length of the largest square that is green is binary searchable.
We can binary search over the length of the square and for a particular length check if there exists some square with that length which is green. If there exists some square of length L that is green then for some L consecutive rows the intersection of columns that are green must be \geq L. For a particular length L iterate over all the rows from i = 0 to N-1-L and check whether the intersection of green columns for the next L consecutive rows (starting from i^{th} row) is \geq L.
Intersection of two column ranges is calculated as
Let p1 and p2 be two column ranges that are green.(p1.F=L and p1.S=R)
pair<int,int> get(pair<int,int> p1, pair<int,int> p2)
{
if (p1.F > p2.F)
swap(p1, p2);
if (p2.F > p1.S)
return {1, 0};// To make length of intersection as 0
return {p2.F, min(p1.S, p2.S)};
}
Segment tree is not used here to get the intersection as it answers a query in O(log(N)) time , where N is the size of the array, which would result in O(Nlog^2(N)) time complexity which is not fast enough to pass the test cases.
We need an efficient way to get the intersection of green columns for L consecutive rows. Sparse table can provide the length of the intersection in O(1) time with O(Nlog(N)) precomputation. Some other data structure like sqrt-tree will also serve the same purpose. Thus we can binary search over the length of side of largest green square and each time the check function inside binary seach algorithm can be implemented in O(N) time. Overall the time complexity of the solution including pre-computation is O(Nlog(N)).
For details of implementation please refer to the attached solutions.
TIME COMPLEXITY:
O(Nlog(N)) for each test case.
SOLUTION:
Setter's solution
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ll long long
#define int long long
#define endl "\n"
#define fi first
#define se second
#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define fr(a,b,c) for(int a=b; a<c; a++)
#define frr(a,b,c) for(int a=b;a>=c;a--)
#define pb push_back
#define pii pair<int,int>
#define R(a) ll a; cin >> a;
#define RS(a) string a; cin >> a;
typedef tree<long long,null_type,greater<long long>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;
typedef tree<long long,null_type,less<long long>,rb_tree_tag,tree_order_statistics_node_update> ordered_set1;
#define RA(a, n) ll a[(n) + 1] = {}; fr(i, 1, (n)+1) {cin >> a[i];}
#define RM(a, n, m) int a[n + 1][m + 1] = {}; fr(i, 1, n+1) {fr(j, 1, m+1) cin >> a[i][j];}
#define reset(X) memset(X, 0, sizeof(X))
using vi=vector<int>;
const int inf = 1e18;
const int mod=998244353;
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
void _print() {cerr << "]"<<endl;}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define deb(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
#define deb(x...)
#endif
#define all(x) (x).begin(),(x).end()
unsigned int power(int x, unsigned int y, int p)
{
int res = 1;
x = x % p;
while (y > 0)
{
if (y & 1)
res = (res*x) % p;
y = y>>1;
x = (x*x) % p;
}
return res;
}
int modInverse(int n, int p)
{
return power(n, p-2, p);
}
const int maxn=1e6+5;
int t[4*maxn][2];
bool f;
void build(int a[], int v, int tl, int tr) {
if (tl == tr) {
if(!f)
t[v][0] = a[tl];
else
t[v][1]=a[tl];
} else {
int tm = (tl + tr) / 2;
build(a, v*2, tl, tm);
build(a, v*2+1, tm+1, tr);
if(!f)
{
t[v][0]= max(t[v*2][0], t[v*2+1][0]);
}
else
t[v][1] = min(t[v*2][1], t[v*2+1][1]);
}
}
int sum(int v, int tl, int tr, int l, int r) {
if (l > r)
{
if(!f)
{
return 0;
}
else
{
return inf;
}
}
if (l == tl && r == tr) {
if(f==0)
return t[v][0];
else
return t[v][1];
}
int tm = (tl + tr) / 2;
if(f==0)
return max(sum(v*2, tl, tm, l, min(r, tm)), sum(v*2+1, tm+1, tr, max(l, tm+1), r));
else
return min(sum(v*2, tl, tm, l, min(r, tm)), sum(v*2+1, tm+1, tr, max(l, tm+1), r));
}
signed main()
{
fastio;
int t=1;
//cin>>t;
while(t--)
{
int n;
cin>>n;
vector<pair<int,int>>v;
int a[n],b[n];
fr(i,0,n)
{
cin>>a[i]>>b[i];
}
build(a,1,0,n-1);
f=1;
build(b,1,0,n-1);
f=0;
int cur=0;
int ans=1;
fr(i,0,n)
{
int x1 = sum(1,0,n-1,cur,i);
f=1;
int x2 = sum(1,0,n-1,cur,i);
f=0;
int xx = x2-x1+1;
int yy = i-cur+1;
// cout<<x1<<" "<<x2<<endl;
if(xx<=0)cur=i;
else
{
ans = max(ans, min(i-cur+1,xx));
if(xx<i-cur+1)
{
cur+=1;
i-=1;
}
else
{
continue;
}
}
}
cout<<ans<<endl;
}
}
Tester-1's Solution
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast,unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#ifndef ONLINE_JUDGE
#define debug(x) cerr<<#x<<" "; _print(x); cerr<<nline;
#else
#define debug(x);
#endif
#define ll long long
/*
------------------------Input Checker----------------------------------
*/
long long readInt(long long l,long long r,char endd){
long long x=0;
int cnt=0;
int fi=-1;
bool is_neg=false;
while(true){
char g=getchar();
if(g=='-'){
assert(fi==-1);
is_neg=true;
continue;
}
if('0'<=g && g<='9'){
x*=10;
x+=g-'0';
if(cnt==0){
fi=g-'0';
}
cnt++;
assert(fi!=0 || cnt==1);
assert(fi!=0 || is_neg==false);
assert(!(cnt>19 || ( cnt==19 && fi>1) ));
} else if(g==endd){
if(is_neg){
x= -x;
}
if(!(l <= x && x <= r))
{
cerr << l << ' ' << r << ' ' << x << '\n';
assert(1 == 0);
}
return x;
} else {
assert(false);
}
}
}
string readString(int l,int r,char endd){
string ret="";
int cnt=0;
while(true){
char g=getchar();
assert(g!=-1);
if(g==endd){
break;
}
cnt++;
ret+=g;
}
assert(l<=cnt && cnt<=r);
return ret;
}
long long readIntSp(long long l,long long r){
return readInt(l,r,' ');
}
long long readIntLn(long long l,long long r){
return readInt(l,r,'\n');
}
string readStringLn(int l,int r){
return readString(l,r,'\n');
}
string readStringSp(int l,int r){
return readString(l,r,' ');
}
/*
------------------------Main code starts here----------------------------------
*/
const ll MOD=1e9+7;
vector<ll> readv(ll n,ll l,ll r){
vector<ll> a;
ll x;
for(ll i=1;i<n;i++){
x=readIntSp(l,r);
a.push_back(x);
}
x=readIntLn(l,r);
a.push_back(x);
return a;
}
const ll MAX=3000300;
void solve(){
ll n=readIntLn(1,1e6);
vector<ll> a(n+5),b(n+5);
for(ll i=1;i<=n;i++){
a[i]=readIntSp(0,n-1);
b[i]=readIntLn(a[i],n-1);
}
ll ans=0,l=0;
multiset<ll> lft,rght;
lft.insert(n+1); rght.insert(-1);
a[0]=n+1,b[0]=-1;
for(ll i=1;i<=n;i++){
lft.insert(a[i]); rght.insert(b[i]);
while(1){
auto il=*(--lft.end()),ir=*(rght.begin());
if(ir-il+1<i-l+1){
lft.erase(lft.find(a[l])); rght.erase(rght.find(b[l]));
l++;
}
else{
break;
}
}
ans=max(ans,i-l+1);
}
cout<<ans;
return;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
freopen("error.txt", "w", stderr);
#endif
ll test_cases=1 ;//readIntLn(1,100);
while(test_cases--){
solve();
}
assert(getchar()==-1);
return 0;
}
Tester-2's Solution
// Jai Shree Ram
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define ll long long
#define int long long
#define pb push_back
#define all(v) v.begin(),v.end()
#define endl "\n"
#define x first
#define y second
#define gcd(a,b) __gcd(a,b)
#define mem1(a) memset(a,-1,sizeof(a))
#define mem0(a) memset(a,0,sizeof(a))
#define sz(a) (int)a.size()
#define pii pair<int,int>
#define hell 1000000007
#define elasped_time 1.0 * clock() / CLOCKS_PER_SEC
template<typename T1,typename T2>istream& operator>>(istream& in,pair<T1,T2> &a){in>>a.x>>a.y;return in;}
template<typename T1,typename T2>ostream& operator<<(ostream& out,pair<T1,T2> a){out<<a.x<<" "<<a.y;return out;}
template<typename T,typename T1>T maxs(T &a,T1 b){if(b>a)a=b;return a;}
template<typename T,typename T1>T mins(T &a,T1 b){if(b<a)a=b;return a;}
// -------------------- Input Checker Start --------------------
long long readInt(long long l, long long r, char endd)
{
long long x = 0;
int cnt = 0, fi = -1;
bool is_neg = false;
while(true)
{
char g = getchar();
if(g == '-')
{
assert(fi == -1);
is_neg = true;
continue;
}
if('0' <= g && g <= '9')
{
x *= 10;
x += g - '0';
if(cnt == 0)
fi = g - '0';
cnt++;
assert(fi != 0 || cnt == 1);
assert(fi != 0 || is_neg == false);
assert(!(cnt > 19 || (cnt == 19 && fi > 1)));
}
else if(g == endd)
{
if(is_neg)
x = -x;
if(!(l <= x && x <= r))
{
cerr << l << ' ' << r << ' ' << x << '\n';
assert(false);
}
return x;
}
else
{
assert(false);
}
}
}
string readString(int l, int r, char endd)
{
string ret = "";
int cnt = 0;
while(true)
{
char g = getchar();
assert(g != -1);
if(g == endd)
break;
cnt++;
ret += g;
}
assert(l <= cnt && cnt <= r);
return ret;
}
long long readIntSp(long long l, long long r) { return readInt(l, r, ' '); }
long long readIntLn(long long l, long long r) { return readInt(l, r, '\n'); }
string readStringLn(int l, int r) { return readString(l, r, '\n'); }
string readStringSp(int l, int r) { return readString(l, r, ' '); }
void readEOF() { assert(getchar() == EOF); }
vector<int> readVectorInt(int n, long long l, long long r)
{
vector<int> a(n);
for(int i = 0; i < n - 1; i++)
a[i] = readIntSp(l, r);
a[n - 1] = readIntLn(l, r);
return a;
}
// -------------------- Input Checker End --------------------
int solve(){
int n = readIntLn(1,1e6);
vector<pii>segs;
for(int i = 0; i < n; i++){
int x = readIntSp(0,n - 1);
int y = readIntLn(x,n - 1);
segs.push_back({x,y});
}
vector<vector<int>> mx(22,vector<int>(n + 1));
auto mn = mx;
vector<int> LOG(n + 1);
for(int i = 0; i < n; i++){
mx[0][i] = segs[i].x;
mn[0][i] = segs[i].y;
}
for(int i = 2; i <= n; i++){
LOG[i] = 1 + LOG[i/2];
}
for(int x = 1; x <= 21; x++){
for(int i = 0; i + (1 << (x - 1)) < n; i++){
mx[x][i] = max(mx[x - 1][i],mx[x - 1][i + (1 << (x - 1))]);
mn[x][i] = min(mn[x - 1][i],mn[x - 1][i + (1 << (x - 1))]);
}
}
auto query = [&](int l,int r){
int j = LOG[r - l + 1];
int mxx = max(mx[j][l],mx[j][r - (1 << j) + 1]);
int mnn = min(mn[j][l],mn[j][r - (1 << j) + 1]);
return mnn - mxx + 1;
};
int ans = 1;
for(int i = 0; i < n; i++){
int mxL = segs[i].x;
int mnR = segs[i].y;
int R = i;
int L = 0;
while(L <= R){
int M = (L + R)/2;
int val = query(M,i);
if(val >= i - M + 1){
ans = max(ans,i - M + 1);
R = M - 1;
}else{
L = M + 1;
}
}
}
cout << ans << endl;
return 0;
}
signed main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#ifdef SIEVE
sieve();
#endif
#ifdef NCR
init();
#endif
int t=1;//cin>>t;
while(t--){
solve();
}
return 0;
}
This text will be hidden
Editorialist's Solution
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define all(_obj) _obj.begin(), _obj.end()
#define F first
#define S second
#define pll pair<ll, ll>
#define vll vector<ll>
ll INF = 1e18;
const int N = 1e6 + 11, mod = 1e9 + 7;
ll max(ll a, ll b) { return ((a > b) ? a : b); }
ll min(ll a, ll b) { return ((a > b) ? b : a); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
pll st[N][26];
int lg[N + 1];
pll get(pll p1, pll p2)
{
if (p1.F > p2.F)
swap(p1, p2);
if (p2.F > p1.S)
return {1, 0};
return {p2.F, min(p1.S, p2.S)};
}
int int_len(int L, int R)
{
int j = lg[R - L + 1];
pll p = get(st[L][j], st[R - (1 << j) + 1][j]);
return p.S - p.F + 1;
}
void sol(void)
{
int n;
cin >> n;
vector<pll> vp(n);
for (int i = 0; i < n; i++)
cin >> vp[i].F >> vp[i].S;
for (int i = 0; i < n; i++)
st[i][0] = vp[i];
for (int j = 1; j <= 25; j++)
for (int i = 0; i + (1 << j) <= n; i++)
st[i][j] = get(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
lg[1] = 0;
for (int i = 2; i <= N; i++)
lg[i] = lg[i / 2] + 1;
int l = 1, r = n, mid;
while (l <= r)
{
mid = (l + r) / 2;
bool istrue = false;
for (int i = 0; i <= n - mid; i++)
{
if (int_len(i, i + mid - 1) >= mid)
istrue = true;
}
if (istrue)
l = mid + 1;
else
r = mid - 1;
}
cout << r;
return;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL), cout.tie(NULL);
int test = 1;
// cin>>test;
while (test--)
sol();
}