답안 #409739

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
409739 2021-05-21T12:45:52 Z AugustinasJucas Sails (IOI07_sails) C++14
100 / 100
395 ms 8688 KB
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
struct treap{
    struct node{
        int l= -1, r = -1, val;
        int sz = 0;
        long long w = 0;
        int pl = 0;
    };
    int curRoot = -1;
    vector<node> tree;
    int dbInd = 0;
    int newN(int x){
		tree[dbInd].sz = 1;
        tree[dbInd].w = rand();
        tree[dbInd].val = x;
        return dbInd++;
    }
    void upd(int v){
		if(v == -1) return ;
		tree[v].sz = 1;
		if(tree[v].l != -1){
			tree[v].sz += tree[tree[v].l].sz;
			tree[tree[v].l].pl += tree[v].pl;
		}
		if(tree[v].r != -1){
			tree[v].sz += tree[tree[v].r].sz;
			tree[tree[v].r].pl += tree[v].pl;
		}
		tree[v].val += tree[v].pl;
		tree[v].pl = 0;
    }
    int merge(int l, int r){
		upd(l);
		upd(r);
        if(l == -1) return r;
        if(r == -1) return l;
        if(tree[l].w > tree[r].w){ // l auksciau
            int R = merge(tree[l].r, r);
            tree[l].r = R;
            upd(l);
            return l;
        }else{
            int R = merge(l, tree[r].l);
            tree[r].l = R;
            upd(r);
            return r;
        }
    }
    pair<int, int> split(int v, int x){ // [0; x] bus kairej
		upd(v);
		if(v == -1) return {-1, -1};
        int lsz = 0;
        if(tree[v].l != -1){
			lsz += tree[tree[v].l].sz;
		}
		if(x >= lsz){ // as priklausau kairei
			auto sp = split(tree[v].r, x-lsz-1);
			tree[v].r = sp.first;
			upd(v);
			return {v, sp.second};
		}else{ // as desinei
			auto sp = split(tree[v].l, x);
			tree[v].l = sp.second;
			upd(v);
			return {sp.first, v};
		}
    }
    void push_back(int x){
		int st = newN(x);
		if(curRoot == -1){
			curRoot = st;
			return;
		}
		curRoot = merge(curRoot, st);
	}
	void push_front(int x){
		int st = newN(x);
		if(curRoot == -1){
			curRoot = st;
			return;
		}
		curRoot = merge(st, curRoot);
	}
	void add(int v, int L, int R, int x, int sl, int sr){
		if(v == -1) return ;
		upd(v);
		if(L <= sl && sr <= R){
			tree[v].pl += x;
			upd(v);
		}else if(R < sl || sr < L){
			return ;
		}else{
			int lft = 0; if(tree[v].l != -1) lft = tree[tree[v].l].sz;
			add(tree[v].l, L, R, x, sl, sl + lft-1);
			add(tree[v].r, L, R, x, sl + lft + 1, sr);
			if(L <= sl + lft && sl+lft <= R){
				tree[v].val += x;
			}
		}
	}
	void add(int l, int r, int x){
		add(curRoot, l, r, x, 0, tree[curRoot].sz-1);
	}
	int get(int v, int x){
		if(v == -1) return v;
		upd(v);
		int lsz = 0;
        if(tree[v].l != -1){
			lsz += tree[tree[v].l].sz;
		}
		if(x == lsz){
			return tree[v].val;
		}
		if(lsz < x){
			return get(tree[v].r, x-lsz-1);
		}else{
			return get(tree[v].l, x);
		}
	}
	int get(int x){ // gauna x-aji elementa
		return get(curRoot, x);
	}
	int desn(int v, int x, int curInd){ // desiniausias <= x indeksas
		if(v == -1) {
			return -1000000;
		}
		upd(v);
		if(tree[v].val <= x){
			if(tree[v].r == -1) return curInd;
			int lsz = 0; 
			int u = tree[v].r;
			if(tree[u].l != -1) lsz += tree[tree[u].l].sz;
			return max(curInd, desn(tree[v].r, x, lsz + curInd+1));
		}else{
			if(tree[v].l == -1) return -1;
			int rsz = 0; 
			int u = tree[v].l;
			if(tree[u].r != -1) rsz += tree[tree[u].r].sz;
			return desn(tree[v].l, x, curInd - rsz -1);
		}
	}
	int kair(int v, int x, int curInd){ // desiniausias <= x indeksas
		if(v == -1) {
			return 1000000;
		}
		upd(v);
		if(tree[v].val < x){
			if(tree[v].r == -1) return 1000000;
			int lsz = 0; 
			int u = tree[v].r;
			if(tree[u].l != -1) lsz += tree[tree[u].l].sz;
			return kair(tree[v].r, x, lsz + curInd+1);
		}else if(tree[v].val > x){
			if(tree[v].l == -1) return 1000000;
			int rsz = 0; 
			int u = tree[v].l;
			if(tree[u].r != -1) rsz += tree[tree[u].r].sz;
			return kair(tree[v].l, x, curInd - rsz -1);
		}else{
			if(tree[v].l == -1) return curInd;
			int rsz = 0; 
			int u = tree[v].l;
			if(tree[u].r != -1) rsz += tree[tree[u].r].sz;
			return min(curInd, kair(tree[v].l, x, curInd - rsz -1));
		}
	}
	int desn(int x){
		int lsz = 0;
		if(tree[curRoot].l != -1){
			lsz += tree[tree[curRoot].l].sz;
		}
		return desn(curRoot, x, lsz);
	}
	int kair(int x){ // randa kairiausia x elementa, kai x egzistuoja
		int lsz = 0;
		if(tree[curRoot].l != -1){
			lsz += tree[tree[curRoot].l].sz;
		}
		return kair(curRoot, x, lsz);
	}
	void print(int v = -2){
		if(v == -2) v = curRoot;
		if(v == -1) return;
		upd(v);
		print(tree[v].l);
		cout << tree[v].val << " ";
		print(tree[v].r);
	} 
	void del(int l, int r){
		cout << "del " << l << "; " << r << endl;
		auto prm = split(curRoot, r);
		cout << "prm: " << prm.first << "; " << prm.second << endl;
		auto ant = split(prm.first, l-1);
		curRoot = merge(ant.first, prm.second);
	}
	void pr(int v = -2){
		if(v == -2) v = curRoot;
		if(v == -1) return;
		pr(tree[v].l);
		int lsz = 0;
        if(tree[v].l != -1){
			lsz += tree[tree[v].l].sz;
		}
		cout << "esu ant " << v << ", jo val = " << tree[v].val << ", o lft = " << lsz  <<  ", kaireje yra " << tree[v].l << ", desineje - " << tree[v].r << endl;
		pr(tree[v].r);
	} 

    treap(){
		tree.resize(2e5);
    }
};
const int dydis = 1e5 + 10;
vector<pair<int, int> > vec;
int n;
int kek[dydis] = {};
treap ms;
void test(){
	
	for(int i = 0; i < 10; i++){
		int a; cin >> a;
		ms.push_back(a);
		cout << "db masyvas: "; ms.print();
		cout << endl; 
	}
	for(int i = 0; i < 10; i++){
		int x; cin >> x; 
		cout << ms.kair(x) << endl;
	}
	for(int i = 0; i < 4; i++){
		int l, r, a; cin >> l >> r >> a;
		ms.add(l, r, a);
		//cout << "db masyvas: "; ms.print();
		//cout << endl; 
	}
	//cout << "db masyvas: "; ms.print();
	//cout << endl; 
	/*
0 0 0 0 0 0 0 0 0 0
0 9 8
2 3 3
0 0 5
4 9 10
13 8 11 11 18 18 18 18 18 18
*/
	while(true){
		int l, r; cin >> l >> r; l--; r--;
		ms.del(l, r);
		cout << "db masyvas: "; ms.print();
		cout << endl; 
	}
	exit(0);
}
int main(){
	//test();
    cin >> n;
    for(int i = 0; i < n; i++){
        int a, b; cin >> a >> b;
        vec.push_back({a, b});
    }
    sort(vec.begin(), vec.end());
    int curHe = 0;
    for(auto x : vec){
        while(x.first != curHe){
			curHe++;
			ms.push_front(0);
		}
		int kek = x.second;
		int kas = ms.get(kek-1);
		
		int r = ms.desn(kas);
		int l = ms.kair(kas);
		
		int reiks = (kek-1)-l + 1;
		
		// intervalas [r-reiks + 1; r] ++;
		// intervalas [0; l-1]++
		ms.add(0, l-1, 1);
		ms.add(r-reiks+1, r, 1);
		// [0; pln]
		
    }
    long long ans = 0;
    for(int i = 0; i < ms.tree[ms.curRoot].sz; i++){
		long long sk = ms.get(i);
        ans += 1ll * sk *( sk-1) / 2ll;
    }
    cout << ans;
    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 6476 KB Output is correct
2 Correct 5 ms 6576 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 6484 KB Output is correct
2 Correct 4 ms 6476 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 4 ms 6576 KB Output is correct
2 Correct 4 ms 6476 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5 ms 6576 KB Output is correct
2 Correct 6 ms 6476 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 10 ms 6604 KB Output is correct
2 Correct 60 ms 6476 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 40 ms 6752 KB Output is correct
2 Correct 72 ms 7136 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 63 ms 7264 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 176 ms 7624 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 337 ms 8488 KB Output is correct
2 Correct 314 ms 8504 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 289 ms 8688 KB Output is correct
2 Correct 231 ms 8316 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 395 ms 8532 KB Output is correct
2 Correct 270 ms 8520 KB Output is correct