Submission #300152

#TimeUsernameProblemLanguageResultExecution timeMemory
300152model_codeComparing Plants (IOI20_plants)Java
100 / 100
3246 ms108264 KiB
// plants-yanhao-2k

import java.util.TreeMap;
import java.util.ArrayList;

class segtree {
	final int n_bits=18;
	final int inf = (int)1e9;
	int[] arr = new int [1<<(n_bits+1)];
	int[] lazyadd = new int [1<<(n_bits+1)];
    int node = 1;
    int lazy = 0;
	int low(int i) {
		return (i<<(Integer.numberOfLeadingZeros(i)-31+n_bits))-(1<<n_bits);
	}
	int high(int i) {
		return ((i+1)<<(Integer.numberOfLeadingZeros(i)-31+n_bits))-(1<<n_bits)-1;
	}
    void build(int[] v) {
        for(int i=0; i<(1<<n_bits); i++) {
            arr[i+(1<<n_bits)] = (i<v.length ? v[i] : inf);
        }
        for(int i=(1<<n_bits)-1; i>=1; i--) {
            arr[i] = Math.min(arr[2*i], arr[2*i+1]);
        }
        for(int i=0; i<(1<<(n_bits+1)); i++) {
            lazyadd[i] = 0;
        }
    }
    int value(int node) {
        arr[node] += lazyadd[node];
        if(node<(1<<n_bits)) {
            lazyadd[2*node] += lazyadd[node];
            lazyadd[2*node+1] += lazyadd[node];
        }
        lazyadd[node] = 0;
        return arr[node];
    }
    void update(int node, int left, int right, int change) {
        if(right>=high(node) && left<=low(node)) {
            lazyadd[node] += change;
        } else if(right<low(node) || left>high(node)) {
            return;
        } else {
            update(2*node, left, right, change);
            update(2*node+1, left, right, change);
            arr[node] = Math.min(value(node*2), value(node*2+1));
        }
    }

    void decr(int left, int right) {
        update(1, left, right, -1);
    }

    int find_zero(int node, int lt, int rg) {
        if(rg<low(node) || lt>high(node)) {
            return -1;
        }
        if(value(node)!=0) {
            return -1;
        }
        if(node >= (1<<n_bits)) {
            return arr[node]==0 ? node-(1<<n_bits) : -1;
        }
        int x = find_zero(node*2, lt, rg);
        if(x!=-1) return x;
        return find_zero(node*2+1, lt, rg);
    }
};

class plants {
	int[] ans;
	int[] lt;
	int[] rg;
	int[][] jump_lt;
	int[][] jump_rg;
	int k_global;
	segtree s = new segtree();
	int ctr = 0;
	int n;
	int[] permutation;
	int blocking(int rg, int k) {
		int lt = rg - k + 1;
		if(lt<0) {
			int p = s.find_zero(1, lt+n, n-1);
			if(p!=-1) {
				return p;
			}
			return s.find_zero(1,0,rg);
		} else {
			return s.find_zero(1,Math.max(0,lt),rg);
		}
	}

	void pull(int idx, int k) {
		int x;
		while((x=blocking(idx,k))!=idx) {
			pull(x,k);
		}
		permutation[idx] = ctr;
		ctr++;
		// decrement the k values before it, and push value in
		if(idx >= k-1) {
			s.update(1, idx-(k-1), idx, -1);
		} else {
			s.decr(0, idx);
			s.decr(idx-(k-1)+n, n-1);
		}
		s.update(1, idx, idx, 1<<29);
	}

	void init(int k, int[] r) {
		k_global = k;
		s.build(r);
		n = r.length;
		lt = new int[n+1];
		rg = new int[n+1];
		permutation = new int[n];
		while(ctr<n) {
			int p = s.find_zero(1,0,n-1);
			assert(p!=-1);
			pull(p,k);
		}
		TreeMap<Integer, Integer> m = new TreeMap<>();
		for (int i=0; i<k; i++) {
			m.put(permutation[i], i);
		}
		m.put(1<<20, n);
		ans = new int[n+1];
		for(int i=0; i<n; i++) {
			rg[i] = m.higherEntry(permutation[i]).getValue();
			lt[(i+k-1)%n] = m.higherEntry(permutation[(i+k-1)%n]).getValue();
			m.remove(permutation[i]);
			m.put(permutation[(i+k)%n], (i+k)%n);
		}
		jump_lt = new int[18][n];
		jump_rg = new int[18][n];
		for(int i=0; i<n; i++) {
			jump_lt[0][i] = lt[i]==n ? 0 : (i+n-lt[i])%n;
			jump_rg[0][i] = rg[i]==n ? 0 : (rg[i]+n-i)%n;
		}
		for(int i=1; i<18; i++) {
			for(int j=0; j<n; j++) {
				jump_lt[i][j] = jump_lt[i-1][j] + jump_lt[i-1][(j+n-jump_lt[i-1][j])%n];
				jump_rg[i][j] = jump_rg[i-1][j] + jump_rg[i-1][(j+n+jump_rg[i-1][j])%n];
				if(jump_lt[i][j]>n) {
					jump_lt[i][j] = 0;
				}
				if(jump_rg[i][j]>n) {
					jump_rg[i][j] = 0;
				}
			}
		}		
	}
	
	int compare_plants(int x, int y) {
		// check for the direct x->y path
		int z = x;
		for(int i=17; i>=0; i--) {
			if(jump_rg[i][z] < y-z) {
				z = z + jump_rg[i][z];
			}
		}
		if(permutation[z] < permutation[y] && (y-z+n)%n < k_global) return 1;
		// direct y->x path
		z = y;
		for(int i=17; i>=0; i--) {
			if(jump_lt[i][z] < z-x) {
				z = z - jump_lt[i][z];
			}
		}
		if(permutation[z] < permutation[x] && (z-x+n)%n < k_global) return -1;
		
		// look for x->y wraparounds
		z = x;
		for(int i=17; i>=0; i--) {
			if(jump_lt[i][z] < (z+n-y)%n) {
				z = (z + n - jump_lt[i][z])%n;
			}
		}
		if(permutation[z] < permutation[y] && (z-y+n)%n < k_global) return 1;
		
		// look for y->x wraparounds
		z = y;
		for(int i=17; i>=0; i--) {
			if(jump_rg[i][z] < (x+n-z)%n) {
				z = (z + jump_rg[i][z])%n;
			}
		}
		if(permutation[z] < permutation[x] && (x-z+n)%n < k_global) return -1;
		
		return 0;
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...