Submission #1043732

# Submission time Handle Problem Language Result Execution time Memory
1043732 2024-08-04T15:10:38 Z nightfal Comparing Plants (IOI20_plants) C++17
15 / 100
686 ms 55236 KB
// #include "plants.h"
#include <iostream>
#include <cstdio>
#include <cassert>
#include <vector>
#include <utility>
#include <tuple>
#include <algorithm>



// using namespace std;
#define maxVal 1'000'000'001
static std:: vector<int> inc,dec,rank,lz,lzr,reach,reach2;
static std:: vector<std::pair<int,int>> t,tr;
static std:: vector<std::vector<int>> g, gt, path;
static int l,m,q2,subtask;
void print(std::pair<int,int> p) {std::cout << "(" << p.first << "," << p.second << ") "; };
void print(std::vector<int> &v) {for(int elem: v) std::cout << elem << " "; std::cout << std::endl;}
void print(std::vector<std::vector<int>> &v) {for (auto elem: v) print(elem); std::cout << std::endl;}
void print(std::vector<std::pair<int,int>> &v) {for(auto [a,b]: v) std::cout << "(" << a << "," << b << ") ";std::cout << std::endl;}

std::pair<int,int> update(std::vector<std::pair<int,int>> &t, std::vector<int> &lz, int node,int start,int end,int left,int right,int diff) {
    if (left <= start and end <= right) lz[node] += diff;
    if (start!=end) { lz[2*node] += lz[node]; lz[2*node+1] += lz[node];}
    t[node].first += lz[node]; lz[node]=0;
    if (right < start or end < left) return {maxVal,m+1};
    if (left <= start and end <= right) return t[node];

    int mid=(start+end)/2;
    auto ans1  = update(t,lz,2*node,start,mid,left,right,diff);
    auto ans2  = update(t,lz,2*node+1,mid+1,end,left,right,diff);
    auto ans = std::min(ans1,ans2);
    t[node] = std::min(t[2*node],t[2*node+1]);
    return ans;    
}
std::pair<int,int> findMin(std::vector<std::pair<int,int>> &t, std::vector<int> &lz, int node, int start, int end, int left, int right) {
    if (start!=end) {lz[2*node] += lz[node]; lz[2*node+1] += lz[node];}
    t[node].first += lz[node]; lz[node]=0;
    if (right < start or end < left) return {maxVal,m+1};
    if (left <= start and end <= right) return t[node];
    
    int mid=(start+end)/2;
    auto min1 = findMin(t,lz,2*node,start,mid,left,right);
    auto min2 = findMin(t,lz,2*node+1,mid+1,end,left,right);
    auto ans = std::min(min1,min2);
    t[node] = std::min(t[2*node],t[2*node+1]);    
    return ans;
}
void segInit(int node, int start, int end, std::vector<int> &r, std::vector<std::pair<int,int>> &t) {
    if (start==end) {t[node]={r[start],start}; return;}
    int mid=(start+end)/2;
    segInit(2*node,start,mid,r,t);
    segInit(2*node+1,mid+1,end,r,t);
    t[node] = std::min(t[2*node],t[2*node+1]);
    return;
}
int findPreMinI(int k,int minI1) {
    if (minI1>0) {
        auto[min2,minI2] = findMin(t,lz,1,0,m-1,std::max(0,minI1-k+1),minI1-1);
        if (min2==0) minI1 = minI2;
    }
    if (minI1-k+1<0) {
        auto[min2,minI2] = findMin(t,lz,1,0,m-1,minI1-k+1+m,m-1);
        if (min2==0) minI1 = minI2;
    }
    return minI1;
}
int computeRank(int minI1, int k, int ranking) {

    if (rank[minI1]!=m) return ranking;
    int minI2 = findPreMinI(k,minI1);

    while (minI2 != minI1) {
        ranking = computeRank(minI2,k,ranking); 
        minI2 = findPreMinI(k,minI1);
    }
    rank[minI1] = ranking--;
    update(t,lz,1,0,m-1,minI1,minI1,m-1);
    update(t,lz,1,0,m-1,std::max(0,minI1-k+1),minI1-1,-1);
    if (minI1-k+1<0) update(t,lz,1,0,m-1,minI1-k+1+m,m-1,-1);

    return ranking;
}
void reachable(int node, std::vector<std::vector<int>> &g, std::vector<int> &reach) {
    if (node==-1 or reach[node]) return;
    reach[node] = 1;
    for(int elem: g[node])
        reachable(elem,g,reach);
    return;
}
void calReachability(int k) {
    tr.resize(4*m); lzr.resize(4*m);
    std::vector<std::pair<int,int>> rankInv;
    for(int i=0; i<m; i++) {rank[i] = -rank[i]; rankInv.push_back({rank[i],i}); }
    sort(rankInv.begin(),rankInv.end());
    segInit(1,0,m-1,rank,tr);
    // std::cout << "rank: "; print(rank);
    // std::cout << "rankInv: "; print(rankInv);
    // std::cout << "tr: "; print(tr);
    g.resize(m,std::vector<int>(2,-1)); gt.resize(m);
    
    for(auto [val,i]: rankInv) {
        std::pair<int,int> temp1, temp2;
        temp1 = temp2 = findMin(tr,lzr,1,0,m-1,std::max(0,i-k+1),i-1);
        if (i-k+1<0) temp2 = findMin(tr,lzr,1,0,m-1,i-k+1+m,m-1);
        temp1 = std::min(temp1,temp2);
        if (temp1.first <=0) {g[i][0] = temp1.second;gt[temp1.second].push_back(i);}
        // std::cout << "i=" << i << ", temp1.second:" << temp1.second << std::endl;

        temp1 = temp2 = findMin(tr,lzr,1,0,m-1,i+1,std::min(m-1,i+k-1));
        if (i+k-1>m-1) temp2 = findMin(tr,lzr,1,0,m-1,0,i+k-1-m);
        temp1 = std::min(temp1,temp2);
        if (temp1.first <= 0) {g[i][1] = temp1.second;gt[temp1.second].push_back(i);}
        // std::cout << "i=" << i << ", temp1.second:" << temp1.second << std::endl;
        update(tr,lzr,1,0,m-1,i,i,m);
        // std::cout << "tr: "; print(tr); std::cout << std::endl;
    }

    // print(gt);
    reach.resize(m); reach2.resize(m);
    reachable(0,g,reach);
    reachable(0,gt,reach2);
    return;
}
void init6(int k, std::vector<int> &r) {
    int n = r.size(); 
    t.resize(4*n); lz.resize(4*n); 
    segInit(1,0,n-1,r,t);
    rank.resize(n,n);
    int ranking = n-1;
    while (ranking >=0) {
        auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1);
        ranking = computeRank(minI1,k,ranking);
    }
    calReachability(k);
    return;
}
void transClosure(int n, int k) {
    for (int i=0; i<n; i++)
        for(int j=i-k+1+n; j<=i+k-1+n; j++)
            if (rank[j%n]<rank[i%n]) g[i][j%n]=1;
        for(int x=0; x<n; x++)
        for (int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                g[i][j] = g[i][j] or g[i][x] and g[x][j];
    
    return;
}
void init5(int k, std::vector<int> &r) {
    int n = r.size(); 
    t.resize(4*n); lz.resize(4*n); g.resize(n,std::vector<int>(n));
    segInit(1,0,n-1,r,t);
    rank.resize(n,n);
    int ranking = n-1;
    while (ranking >=0) {
        auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1);
        ranking = computeRank(minI1,k,ranking);
    }
    transClosure(n, k);
    return;    
}
void init4(int k, std::vector<int> &r) {
    int n = r.size(); 
    t.resize(4*n); lz.resize(4*n);
    segInit(1,0,n-1,r,t);
    rank.resize(n,n);

    int ranking = n-1;
    while (ranking >=0) {
        auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1);
        ranking = computeRank(minI1,k,ranking);
    }
    return;
}
void init3(int k, std::vector<int> &r) {
    int n = r.size(); 
    t.resize(4*n); lz.resize(4*n);
    segInit(1,0,n-1,r,t);
    rank.resize(n,n);

    for(int i=n-1; i>=0; i--) {
        auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1);
        int min2=1, minI2=minI1;
        int min3=1, minI3=minI1;
        if (minI1>0) std::tie(min2,minI2) = findMin(t,lz,1,0,n-1,std::max(0,minI1-(n-k)),minI1-1);
        if (minI1-(n-k)<0) std::tie(min3,minI3) = findMin(t,lz,1,0,n-1,minI1-(n-k)+n,n-1);
        if (min3==0) minI1=minI3;
        else if (min2==0) minI1=minI2;
        rank[minI1] = i;
        update(t,lz,1,0,n-1,minI1,minI1,n-1);
        update(t,lz,1,0,n-1,std::max(0,minI1-k+1),minI1-1,-1);
        if (minI1-k+1<0) update(t,lz,1,0,n-1,minI1-k+1+n,n-1,-1);
    }
    return;
}
int findMax(int k, std::vector<int> &r) {
    int i=2*m-1;
    while (r[i%m]!=0) {i--;}
    int j = i-1;
    while (j > i-k) {
        if (r[j%m]==0) i = j; 
        j--;
    }
    for(int j=i; j>i-k; j--) r[j%m]--;
    return i%m;
}
void init2(int k, std::vector<int> &r) {
    int n = r.size();
    rank.resize(n);
    for(int i=n-1; i>=0; i--)
        rank[findMax(k,r)] = i;   
    return;
}
void init1(int k, std::vector<int> &r) {
    int n = r.size();
    inc.resize(n); dec.resize(n);
    for(int i=0; i<n; i++) {inc[i] = dec[i] = i;}
    int s,incVal,decVal;
    for(s=2*n-1; s>=0; s--) {
        if (r[s%n]==0) incVal = s;
        else decVal = s;
        inc[s%n] = incVal; dec[s%n] = decVal;
    }
    return;
}
void init(int k, std::vector<int> r) {
    int n = r.size(); 
    m=n; l=k;

    init6(k,r); return;
	if(k==2) init1(k, r);
    else if(n<=5000 and 2*k>n) init2(k, r);
    else if(2*k>n) init3(k,r);
    else if (n<=300 and q2 <= n*(n-1)/2) init5(k,r);
    else init4(k,r);
	return;
}
int compare_plants6(int x, int y) {
    if (reach[y]) return 1;
    else if (reach2[y]) return -1;
    else return 0;
}
int compare_plants5(int x, int y) {
    if (g[x][y]) return 1;
    else if (g[y][x]) return -1;
    else return 0;
}
int compare_plants2(int x, int y) {
    if (rank[x]>rank[y]) return 1;
    else return -1;
}
int compare_plants1(int x, int y) {
    if (y <= dec[x] or x+m <= inc[y]) return 1;
    else if (y <= inc[x] or x+m <= dec[y]) return -1;
	return 0;
}
int compare_plants(int x, int y) {
    return compare_plants6(x,y);
  	if(l==2) return compare_plants1(x,y);
    else if(m<=5000 and 2*l>m) return compare_plants2(x,y);
    else if(2*l>m) return compare_plants2(x,y);
    if (m<=300 and q2 <= m*(m-1)/2) return compare_plants5(x,y);
    // else return compare_plants6(x,y);
    else return compare_plants2(x,y);
	return 0;
}

Compilation message

plants.cpp: In function 'void transClosure(int, int)':
plants.cpp:140:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
  140 |     for (int i=0; i<n; i++)
      |     ^~~
plants.cpp:143:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
  143 |         for(int x=0; x<n; x++)
      |         ^~~
plants.cpp:146:46: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  146 |                 g[i][j] = g[i][j] or g[i][x] and g[x][j];
plants.cpp: At global scope:
plants.cpp:17:19: warning: 'subtask' defined but not used [-Wunused-variable]
   17 | static int l,m,q2,subtask;
      |                   ^~~~~~~
plants.cpp: In function 'void init1(int, std::vector<int>&)':
plants.cpp:223:37: warning: 'decVal' may be used uninitialized in this function [-Wmaybe-uninitialized]
  223 |         inc[s%n] = incVal; dec[s%n] = decVal;
plants.cpp:223:18: warning: 'incVal' may be used uninitialized in this function [-Wmaybe-uninitialized]
  223 |         inc[s%n] = incVal; dec[s%n] = decVal;
# Verdict Execution time Memory Grader output
1 Correct 0 ms 348 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Incorrect 0 ms 348 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 348 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Incorrect 0 ms 348 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 348 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Incorrect 0 ms 348 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 0 ms 348 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 0 ms 348 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Incorrect 0 ms 348 KB Output isn't correct
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 344 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 0 ms 348 KB Output is correct
4 Correct 0 ms 348 KB Output is correct
5 Correct 3 ms 604 KB Output is correct
6 Correct 450 ms 51168 KB Output is correct
7 Correct 548 ms 51396 KB Output is correct
8 Correct 686 ms 51904 KB Output is correct
9 Correct 674 ms 55236 KB Output is correct
10 Correct 376 ms 51712 KB Output is correct
11 Correct 517 ms 52648 KB Output is correct
12 Correct 357 ms 53696 KB Output is correct
13 Correct 459 ms 51812 KB Output is correct
14 Correct 571 ms 52416 KB Output is correct
15 Correct 647 ms 53212 KB Output is correct
16 Correct 356 ms 53184 KB Output is correct
17 Correct 437 ms 51392 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 348 KB Output is correct
2 Correct 0 ms 348 KB Output is correct
3 Incorrect 0 ms 348 KB Output isn't correct
4 Halted 0 ms 0 KB -