제출 #21009

#제출 시각아이디문제언어결과실행 시간메모리
21009model_codeArranging Tickets (JOI17_arranging_tickets)C++11
100 / 100
3696 ms19892 KiB
#include<cstdio>
#include<utility>
#include<vector>
#include<algorithm>

using namespace std;

const int MAX_N = 200000;
const int MAX_M = 100000;

typedef pair<int, int> P;

struct Segtree{
	int N;
	long long dat[524288];
	bool flg[524288];
	void init(int N_){
		N = 1;
		while(N < N_) N *= 2;
		for(int i = 1; i < N * 2; ++i){
			dat[i] = 0;
			flg[i] = true;
		}
	}
	void add(int i, long long x){
		i += N;
		int tmp = i;
		int j = -1;
		while(tmp > 0){
			if(flg[tmp]) j = tmp;
			tmp /= 2;
		}
		if(j != -1){
			tmp = i;
			while(tmp > j){
				flg[tmp] = true;
				flg[tmp ^ 1] = true;
				dat[tmp] = 0;
				dat[tmp ^ 1] = 0;
				tmp /= 2;
			}
		}
		while(i > 0){
			flg[i] = false;
			dat[i] += x;
			i /= 2;
		}
	}
	long long getAll(){
		return dat[1];
	}
	void setZero(long long x, int i){
		if(i >= N){
			dat[i] -= x;
		}else{
			long long ri = dat[i * 2 + 1];
			if(x <= ri){
				setZero(x, i * 2 + 1);
			}else{
				dat[i * 2 + 1] = 0;
				flg[i * 2 + 1] = true;
				setZero(x - ri, i * 2);
			}
			dat[i] = dat[i * 2] + dat[i * 2 + 1];
		}
	}
	void setZero(long long x){
		setZero(x, 1);
	}
	
	void restore(int i){
		if(i >= N){
			if(flg[i]) dat[i] = 0;
			return;
		}
		if(flg[i]){
			flg[i * 2] = true;
			flg[i * 2 + 1] = true;
		}
		restore(i * 2);
		restore(i * 2 + 1);
	}
	void restoreAll(){
		restore(1);
	}
	long long get(int i){
		return dat[i + N];
	}
};

Segtree seg;

int N, M;
int A[MAX_M], B[MAX_M], C[MAX_M];

long long sum[MAX_N];
int ml, mr;

long long tmp[MAX_N];

long long need[MAX_N]; // need to flip need[i] people which contain section i
long long added[MAX_N];

vector<P> vecs[MAX_N];

bool check(long long num, int t, long long m){
	// flip num people
	// all contain section t
	// result = m
	
	if(num > m) return false;
	
	for(int i = 0; i < N; ++i){
		vecs[i].clear();
		tmp[i] = 0;
		added[i] = 0;
	}
	seg.init(N);
	for(int i = 0; i < t; ++i){
		need[i] = (sum[i] + num - m + 1) / 2;
	}
	need[t] = num;
	
	for(int i = 0; i < M; ++i){
		if(A[i] <= t && B[i] > t){
			vecs[A[i]].push_back(P(B[i], C[i]));
			tmp[B[i]] += C[i];
		}
	}
	long long flipped = 0;
	for(int i = 0; i <= t; ++i){
		for(int j = 0; j < vecs[i].size(); ++j){
			int b = vecs[i][j].first;
			int c = vecs[i][j].second;
			seg.add(b, c);
		}
		if(flipped < need[i]){
			long long n = need[i] - flipped;
			if(seg.getAll() < n){
				return false;
			}
			seg.setZero(n);
			flipped = need[i];
		}
	}
	if(flipped != num) return false;
	
	seg.restoreAll();
	
	for(int i = t + 1; i < N; ++i){
		long long all = tmp[i];
		long long remained = seg.get(i);
		long long flipped = all - remained;
		added[t] -= flipped;
		added[i] += flipped * 2;
		added[N - 1] -= flipped;
	}
	
	for(int i = t + 1; i < N; ++i){
		added[i] += added[i - 1];
	}
	for(int i = t + 1; i < N; ++i){
		long long x = sum[i] + added[i];
		if(x > m) return false;
	}	
	return true;
}

bool checkAll(long long m){
	// result = m
	bool flg = check(sum[ml] - m, ml, m);
	if(flg) return true;
	flg = check(sum[ml] - (m - 1), ml, m);
	if(flg) return true;
	flg = check(sum[mr] - m, mr, m);
	if(flg) return true;
	flg = check(sum[mr] - (m - 1), mr, m);
	if(flg) return true;
	return false;
}

long long solve(){
	for(int i = 0; i < N; ++i){
		sum[i] = 0;
	}
	for(int i = 0; i < M; ++i){
		if(A[i] > B[i]) swap(A[i], B[i]);
		sum[A[i]] += C[i];
		sum[B[i]] -= C[i];
	}
	for(int i = 1; i < N; ++i){
		sum[i] += sum[i - 1];
	}
	long long ma = 0;
	for(int i = 0; i < N; ++i){
		if(ma < sum[i]) ma = sum[i];
	}
	ml = -1, mr = -1;
	for(int i = 0; i < N; ++i){
		if(ma == sum[i]){
			ml = i;
			break;
		}
	}
	for(int i = N - 1; i >= 0; --i){
		if(ma == sum[i]){
			mr = i;
			break;
		}
	}
	long long lb = 0, ub = ma;
	
	while(ub - lb > 1){
		long long mid = (ub + lb) / 2;
		bool flg = checkAll(mid);
		if(flg){
			ub = mid;
		}else{
			lb = mid;
		}
	}
	return ub;
}

void input(){
	scanf("%d%d", &N, &M);
	for(int i = 0; i < M; ++i){
		scanf("%d%d%d", A + i, B + i, C + i);
		A[i]--;
		B[i]--;
	}
}

int main(){
	input();
	long long ans = solve();
	printf("%lld\n", ans);
	return 0;
	
}

컴파일 시 표준 에러 (stderr) 메시지

arranging_tickets.cpp: In function 'void input()':
arranging_tickets.cpp:226:23: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &N, &M);
                       ^
arranging_tickets.cpp:228:39: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d%d", A + i, B + i, C + i);
                                       ^

#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...