답안 #328533

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
328533 2020-11-17T03:29:07 Z MonkeyKing Salesman (IOI09_salesman) C++14
100 / 100
2760 ms 60780 KB
//Original Code:
//#include <self/utility>
//#include <self/debug>
//using namespace std;
//
//
////quality guarantee
//template <typename T>
//struct SegmentTreeMaxUpdate //[)
//{
//	T minValue = -1e9;
//	T *data = 0;
//	T *tag = 0;
//	int nn;
//	int size()
//	{
//		return nn;
//	}
//	void init(int size)
//	{
//		if (data)
//			delete data;
//		if (tag)
//			delete tag;
//		nn = 1;
//		while (nn < size)
//		{
//			nn <<= 1;
//		}
//		data = new T[nn * 2 + 5];
//		tag = new T[nn * 2 + 5];
//		for (int i = 0; i <= nn * 2; i++)
//		{
//			data[i] = minValue;
//			tag[i] = minValue;
//		}
//	}
//	void pushdown(int x)
//	{
//		if (x >= nn || tag[x]<=minValue) return;
//		data[x * 2] = max(data[x * 2], tag[x]);
//		data[x * 2 + 1] = max(data[x * 2 + 1], tag[x]);
//		tag[x * 2] = max(tag[x * 2], tag[x]);
//		tag[x * 2 + 1] = max(tag[x * 2 + 1], tag[x]);
//		tag[x] = minValue;
//	}
//	void update(int pos, T value)
//	{
//		update(pos, pos + 1, value);
//	}
//	void update(int ql, int qr, T value)
//	{
//		update(1, 0, nn, ql, qr, value);
//	}
//	void update(int x, int l, int r, int ql, int qr, T value)
//	{
//		if (l >= qr || r <= ql)
//			return;
//		pushdown(x);
//		if (l >= ql && r <= qr)
//		{
//			data[x] = max(data[x], value);
//			tag[x] = max(tag[x], value);
//			return;
//		}
//		update(x * 2, l, l + r >> 1, ql, qr, value);
//		update(x * 2 + 1, l + r >> 1, r, ql, qr, value);
//		data[x] = max(data[x * 2], data[x * 2 + 1]);
//	}
//	T query(int pos)
//	{
//		return query(pos,pos+1);
//	}
//	T query(int ql, int qr)
//	{
//		return query(1, 0, nn, ql, qr);
//	}
//	T query(int x, int l, int r, int ql, int qr)
//	{
//		if (l >= qr || r <= ql)
//			return minValue;
//		pushdown(x);
//		if (l >= ql && r <= qr)
//		{
//			return data[x];
//		}
//		return max(query(x * 2, l, l + r >> 1, ql, qr), query(x * 2 + 1, l + r >> 1, r, ql, qr));
//	}
//	~SegmentTreeMaxUpdate()
//	{
//		delete data;
//		delete tag;
//	}
//};
//
//struct SegmentTreeFast:public SegmentTreeMaxUpdate <int>
//{
//	inline void update(int pos,int value)
//	{
//		pos+=nn;
//		while(pos)
//		{
//			chmax(data[pos],value);
//			pos>>=1;
//		}
//	}
//};
//
//SegmentTreeFast sgt1;
//SegmentTreeFast sgt2;
//SegmentTreeMaxUpdate <int> sgt3;
//SegmentTreeMaxUpdate <int> sgt4;
//int n,u,d,s;
//vector <pii> fairs[500005];
//
//namespace DEBUG
//{
//	vector <int> positions={1,2,3,4,5};
//	inline void printProfit()
//	{
//		for(auto &pos:positions)
//		{
//			// assert(sgt1.query(pos)+pos*d==sgt2.query(pos)-pos*u);
//			cout<<sgt1.query(pos)-pos*d<<' ';
//		}
//		cout<<endl;
//	}
//}
//using namespace DEBUG;
//
//int main()
//{
//	freopen("input.txt","r",stdin);
//	scanf("%d%d%d%d",&n,&u,&d,&s);
//	for(int i=0;i<n;i++)
//	{
//		int x,y,z;
//		scanf("%d%d%d",&x,&y,&z);
//		fairs[x].push_back(mp(y,z));
//	}
//	sgt1.init(500005);
//	sgt2.init(500005);
//	sgt3.init(500005);
//	sgt4.init(500005);
//	sgt1.update(s,s*d);
//	sgt2.update(s,-s*u);
//	fairs[500003].push_back(mp(s,0));
//	for(int i=0;i<500005;i++)
//	{
//		// ?????
//		if(fairs[i].empty()) continue;
//		if(fairs[i].size()==1)
//		{
//			int pos=fairs[i][0].first;
//			int p=fairs[i][0].second;
//			int realCost=p+max(sgt1.query(0,pos+1)-pos*d,sgt2.query(pos,500005)+pos*u);
//			sgt1.update(pos,realCost+pos*d);
//			sgt2.update(pos,realCost-pos*u);
//			continue;
//		}
//		sort(all(fairs[i]));
//		sgt3.update(0,500005,-inf);
//		for(auto &fair:fairs[i])
//		{
//			int pos=fair.first;
//			sgt3.update(pos,max(sgt2.query(pos,500005)+pos*u+pos*d,max(sgt3.query(0,pos+1),sgt1.query(0,pos+1)))+fair.second);
//		}
//		reverse(all(fairs[i]));
//		sgt4.update(0,500005,-inf);
//		for(auto &fair:fairs[i])
//		{
//			int pos=fair.first;
//			sgt4.update(pos,max(sgt1.query(0,pos+1)-pos*u-pos*d,max(sgt4.query(pos,500005),sgt2.query(pos,500005)))+fair.second);
//		}
//		for(auto &fair:fairs[i])
//		{
//			int pos=fair.first;
//			int realCost=max(sgt3.query(pos)-pos*d,sgt4.query(pos)+pos*u);
//			sgt1.update(pos,realCost+pos*d);
//			sgt2.update(pos,realCost-pos*u);
//		}
//	}
//	int realCost=max(sgt1.query(s)-s*d,sgt2.query(s)+s*u);
//	cout<<realCost<<endl;
//	return 0;
//}

//substituted with C++ Inliner
#ifndef _SELF_UTILITY
#define _SELF_UTILITY 1
#include <numeric>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <string.h>
#include <stack>
#include <assert.h>
#include <bitset>
#include <time.h>
#define Endl endl
#define mp make_pair
#define ll long long 
#define ull unsigned long long
#define pii pair<int,int>
#define over(A) {cout<<A<<endl;exit(0);}
#define all(A) A.begin(),A.end()
#define quickcin ios_base::sync_with_stdio(false);
#ifdef __TAKE_MOD
int mod;
#else
#ifdef __TAKE_CONST_MOD
const int mod=__TAKE_CONST_MOD;
#else
const int mod=1000000007;
#endif
#endif
const int gmod=5;
const int inf=1039074182;
const double eps=1e-9;
const ll llinf=2LL*inf*inf;
template <typename T1,typename T2> inline void chmin(T1 &x,T2 b) {if(b<x) x=b;}
template <typename T1,typename T2> inline void chmax(T1 &x,T2 b) {if(b>x) x=b;}
inline void chadd(int &x,int b) {x+=b-mod;x+=(x>>31 & mod);}
template <typename T1,typename T2> inline void chadd(T1 &x,T2 b) {x+=b;if(x>=mod) x-=mod;}
template <typename T1,typename T2> inline void chmul(T1 &x,T2 b) {x=1LL*x*b%mod;}
template <typename T1,typename T2> inline void chmod(T1 &x,T2 b) {x%=b,x+=b;if(x>=b) x-=b;}
template <typename T> inline T mabs(T x) {return (x<0?-x:x);}
#endif
using namespace std;
#ifndef _SELF_DEBUG
#define _SELF_DEBUG 1
#ifndef _SELF_OPERATOR
#define _SELF_OPERATOR 1
using namespace std;
template <typename T>
ostream &operator<<(ostream &cout, vector<T> vec)
{
	cout << "{";
	for (int i = 0; i < (int)vec.size(); i++)
	{
		cout << vec[i];
		if (i != (int)vec.size() - 1)
			cout << ',';
	}
	cout << "}";
	return cout;
}

template <typename T>
void operator*=(vector<T> &vec, int k)
{
	for (auto &x : vec)
		x *= k;
}

template <typename T>
void operator-=(vector<T> &a, const vector<T> &b)
{
	assert(a.size() == b.size());
	for (size_t it = 0; it < a.size(); it++)
	{
		a[it] -= b[it];
	}
}

template <typename T>
vector<T> operator*(const vector<T> &vec, int k)
{
	vector<T> res(vec);
	res *= k;
	return res;
}

template <typename T1, typename T2>
ostream &operator<<(ostream &cout, pair<T1, T2> p)
{
	cout << "(" << p.first << ',' << p.second << ")";
	return cout;
}

template <typename T, typename T2>
ostream &operator<<(ostream &cout, set<T, T2> s)
{
	vector<T> t;
	for (auto x : s)
		t.push_back(x);
	cout << t;
	return cout;
}

template <typename T, typename T2>
ostream &operator<<(ostream &cout, multiset<T, T2> s)
{
	vector<T> t;
	for (auto x : s)
		t.push_back(x);
	cout << t;
	return cout;
}

template <typename T>
ostream &operator<<(ostream &cout, queue<T> q)
{
	vector<T> t;
	while (q.size())
	{
		t.push_back(q.front());
		q.pop();
	}
	cout << t;
	return cout;
}

template <typename T1, typename T2, typename T3>
ostream &operator<<(ostream &cout, map<T1, T2, T3> m)
{
	for (auto &x : m)
	{
		cout << "Key: " << x.first << ' ' << "Value: " << x.second << endl;
	}
	return cout;
}

template <typename T>
T operator*(vector<T> v1, vector<T> v2)
{
	assert(v1.size() == v2.size());
	int n = v1.size();
	T res = 0;
	for (int i = 0; i < n; i++)
	{
		res += v1[i] * v2[i];
	}
	return res;
}

template <typename T1, typename T2>
pair<T1, T2> operator+(pair<T1, T2> x, pair<T1, T2> y)
{
	return make_pair(x.first + y.first, x.second + y.second);
}

template <typename T1, typename T2>
void operator+=(pair<T1, T2> &x, pair<T1, T2> y)
{
	x.first += y.first;
	x.second += y.second;
}

template <typename T1, typename T2>
pair<T1, T2> operator-(pair<T1, T2> x)
{
	return make_pair(-x.first, -x.second);
}

template <typename T>
vector<vector<T>> operator~(vector<vector<T>> vec)
{
	vector<vector<T>> v;
	int n = vec.size(), m = vec[0].size();
	v.resize(m);
	for (int i = 0; i < m; i++)
	{
		v[i].resize(n);
	}
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			v[i][j] = vec[j][i];
		}
	}
	return v;
}
#endif
void print0x(int x)
{
	std::vector <int> vec;
	while(x)
	{
		vec.push_back(x&1);
		x>>=1;
	}
	std::reverse(vec.begin(),vec.end());
	for(int i=0;i<(int)vec.size();i++)
	{
		std::cout<<vec[i];
	}
	std::cout<<' ';
}

template <typename T>
void print0x(T x,int len)
{
	std::vector <int> vec;
	while(x)
	{
		vec.push_back(x&1);
		x>>=1;
	}
	reverse(vec.begin(),vec.end());
	for(int i=(int)vec.size();i<len;i++)
	{
		putchar('0');
	}
	for(size_t i=0;i<vec.size();i++)
	{
		std::cout<<vec[i];
	}
	std::cout<<' ';
}
#endif
using namespace std;


//quality guarantee
template <typename T>
struct SegmentTreeMaxUpdate //[)
{
	T minValue = -1e9;
	T *data = 0;
	T *tag = 0;
	int nn;
	int size()
	{
		return nn;
	}
	void init(int size)
	{
		if (data)
			delete data;
		if (tag)
			delete tag;
		nn = 1;
		while (nn < size)
		{
			nn <<= 1;
		}
		data = new T[nn * 2 + 5];
		tag = new T[nn * 2 + 5];
		for (int i = 0; i <= nn * 2; i++)
		{
			data[i] = minValue;
			tag[i] = minValue;
		}
	}
	void pushdown(int x)
	{
		if (x >= nn || tag[x]<=minValue) return;
		data[x * 2] = max(data[x * 2], tag[x]);
		data[x * 2 + 1] = max(data[x * 2 + 1], tag[x]);
		tag[x * 2] = max(tag[x * 2], tag[x]);
		tag[x * 2 + 1] = max(tag[x * 2 + 1], tag[x]);
		tag[x] = minValue;
	}
	void update(int pos, T value)
	{
		update(pos, pos + 1, value);
	}
	void update(int ql, int qr, T value)
	{
		update(1, 0, nn, ql, qr, value);
	}
	void update(int x, int l, int r, int ql, int qr, T value)
	{
		if (l >= qr || r <= ql)
			return;
		pushdown(x);
		if (l >= ql && r <= qr)
		{
			data[x] = max(data[x], value);
			tag[x] = max(tag[x], value);
			return;
		}
		update(x * 2, l, l + r >> 1, ql, qr, value);
		update(x * 2 + 1, l + r >> 1, r, ql, qr, value);
		data[x] = max(data[x * 2], data[x * 2 + 1]);
	}
	T query(int pos)
	{
		return query(pos,pos+1);
	}
	T query(int ql, int qr)
	{
		return query(1, 0, nn, ql, qr);
	}
	T query(int x, int l, int r, int ql, int qr)
	{
		if (l >= qr || r <= ql)
			return minValue;
		pushdown(x);
		if (l >= ql && r <= qr)
		{
			return data[x];
		}
		return max(query(x * 2, l, l + r >> 1, ql, qr), query(x * 2 + 1, l + r >> 1, r, ql, qr));
	}
	~SegmentTreeMaxUpdate()
	{
		delete data;
		delete tag;
	}
};

struct SegmentTreeFast:public SegmentTreeMaxUpdate <int>
{
	inline void update(int pos,int value)
	{
		pos+=nn;
		while(pos)
		{
			chmax(data[pos],value);
			pos>>=1;
		}
	}
};

SegmentTreeFast sgt1;
SegmentTreeFast sgt2;
SegmentTreeMaxUpdate <int> sgt3;
SegmentTreeMaxUpdate <int> sgt4;
int n,u,d,s;
vector <pii> fairs[500005];

namespace DEBUG
{
	vector <int> positions={1,2,3,4,5};
	inline void printProfit()
	{
		for(auto &pos:positions)
		{
			// assert(sgt1.query(pos)+pos*d==sgt2.query(pos)-pos*u);
			cout<<sgt1.query(pos)-pos*d<<' ';
		}
		cout<<endl;
	}
}
using namespace DEBUG;

int main()
{
//	freopen("input.txt","r",stdin);
	scanf("%d%d%d%d",&n,&u,&d,&s);
	for(int i=0;i<n;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		fairs[x].push_back(mp(y,z));
	}
	sgt1.init(500005);
	sgt2.init(500005);
	sgt3.init(500005);
	sgt4.init(500005);
	sgt1.update(s,s*d);
	sgt2.update(s,-s*u);
	fairs[500003].push_back(mp(s,0));
	for(int i=0;i<500005;i++)
	{
		// ?????
		if(fairs[i].empty()) continue;
		if(fairs[i].size()==1)
		{
			int pos=fairs[i][0].first;
			int p=fairs[i][0].second;
			int realCost=p+max(sgt1.query(0,pos+1)-pos*d,sgt2.query(pos,500005)+pos*u);
			sgt1.update(pos,realCost+pos*d);
			sgt2.update(pos,realCost-pos*u);
			continue;
		}
		sort(all(fairs[i]));
		sgt3.update(0,500005,-inf);
		for(auto &fair:fairs[i])
		{
			int pos=fair.first;
			sgt3.update(pos,max(sgt2.query(pos,500005)+pos*u+pos*d,max(sgt3.query(0,pos+1),sgt1.query(0,pos+1)))+fair.second);
		}
		reverse(all(fairs[i]));
		sgt4.update(0,500005,-inf);
		for(auto &fair:fairs[i])
		{
			int pos=fair.first;
			sgt4.update(pos,max(sgt1.query(0,pos+1)-pos*u-pos*d,max(sgt4.query(pos,500005),sgt2.query(pos,500005)))+fair.second);
		}
		for(auto &fair:fairs[i])
		{
			int pos=fair.first;
			int realCost=max(sgt3.query(pos)-pos*d,sgt4.query(pos)+pos*u);
			sgt1.update(pos,realCost+pos*d);
			sgt2.update(pos,realCost-pos*u);
		}
	}
	int realCost=max(sgt1.query(s)-s*d,sgt2.query(s)+s*u);
	cout<<realCost<<endl;
	return 0;
}

Compilation message

salesman.cpp: In instantiation of 'T SegmentTreeMaxUpdate<T>::query(int, int, int, int, int) [with T = int]':
salesman.cpp:492:32:   required from 'T SegmentTreeMaxUpdate<T>::query(int, int) [with T = int]'
salesman.cpp:572:41:   required from here
salesman.cpp:503:32: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  503 |   return max(query(x * 2, l, l + r >> 1, ql, qr), query(x * 2 + 1, l + r >> 1, r, ql, qr));
      |                              ~~^~~
salesman.cpp:503:70: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  503 |   return max(query(x * 2, l, l + r >> 1, ql, qr), query(x * 2 + 1, l + r >> 1, r, ql, qr));
      |                                                                    ~~^~~
salesman.cpp: In instantiation of 'void SegmentTreeMaxUpdate<T>::update(int, int, int, int, int, T) [with T = int]':
salesman.cpp:469:3:   required from 'void SegmentTreeMaxUpdate<T>::update(int, int, T) [with T = int]'
salesman.cpp:578:28:   required from here
salesman.cpp:482:22: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  482 |   update(x * 2, l, l + r >> 1, ql, qr, value);
      |                    ~~^~~
salesman.cpp:483:23: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  483 |   update(x * 2 + 1, l + r >> 1, r, ql, qr, value);
      |                     ~~^~~
salesman.cpp: In function 'int main()':
salesman.cpp:550:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  550 |  scanf("%d%d%d%d",&n,&u,&d,&s);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
salesman.cpp:554:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  554 |   scanf("%d%d%d",&x,&y,&z);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 30 ms 44908 KB Output is correct
2 Correct 30 ms 44908 KB Output is correct
3 Correct 30 ms 44908 KB Output is correct
4 Correct 33 ms 45036 KB Output is correct
5 Correct 36 ms 45036 KB Output is correct
6 Correct 71 ms 45492 KB Output is correct
7 Correct 141 ms 46444 KB Output is correct
8 Correct 251 ms 48108 KB Output is correct
9 Correct 352 ms 49772 KB Output is correct
10 Correct 600 ms 54636 KB Output is correct
11 Correct 709 ms 54380 KB Output is correct
12 Correct 929 ms 57452 KB Output is correct
13 Correct 924 ms 57500 KB Output is correct
14 Correct 1125 ms 60780 KB Output is correct
15 Correct 954 ms 60524 KB Output is correct
16 Correct 1162 ms 60652 KB Output is correct
17 Correct 30 ms 44908 KB Output is correct
18 Correct 31 ms 44908 KB Output is correct
19 Correct 35 ms 44908 KB Output is correct
20 Correct 40 ms 44908 KB Output is correct
21 Correct 39 ms 44908 KB Output is correct
22 Correct 49 ms 45036 KB Output is correct
23 Correct 49 ms 45036 KB Output is correct
24 Correct 48 ms 45036 KB Output is correct
25 Correct 624 ms 46188 KB Output is correct
26 Correct 1116 ms 47080 KB Output is correct
27 Correct 1841 ms 48476 KB Output is correct
28 Correct 2054 ms 48864 KB Output is correct
29 Correct 2760 ms 49900 KB Output is correct
30 Correct 2675 ms 50096 KB Output is correct