首页 > 其他分享 >「NOI2009」诗人小G

「NOI2009」诗人小G

时间:2024-03-28 15:37:24浏览次数:24  
标签:int void tail cerr template print 诗人 NOI2009

决策单调性 #dp

满足决策单调性,双端队列维护,可以二分出每两个限制的边界位置

// Author: xiaruize
#ifndef ONLINE_JUDGE
bool start_of_memory_use;
#else
#define debug(x)
#endif
#include <bits/stdc++.h>
using namespace std;
#ifndef ONLINE_JUDGE
clock_t start_clock = clock();
#endif
namespace __DEBUG_UTIL__
{
	using namespace std;
	/* Primitive Datatypes Print */
	void print(const char *x) { cerr << x; }
	void print(bool x) { cerr << (x ? "T" : "F"); }
	void print(char x) { cerr << '\'' << x << '\''; }
	void print(signed short int x) { cerr << x; }
	void print(unsigned short int x) { cerr << x; }
	void print(signed int x) { cerr << x; }
	void print(unsigned int x) { cerr << x; }
	void print(signed long int x) { cerr << x; }
	void print(unsigned long int x) { cerr << x; }
	void print(signed long long int x) { cerr << x; }
	void print(unsigned long long int x) { cerr << x; }
	void print(float x) { cerr << x; }
	void print(double x) { cerr << x; }
	void print(long double x) { cerr << x; }
	void print(string x) { cerr << '\"' << x << '\"'; }
	template <size_t N>
	void print(bitset<N> x) { cerr << x; }
	void print(vector<bool> v)
	{ /* Overloaded this because stl optimizes vector<bool> by using
		  _Bit_reference instead of bool to conserve space. */
		int f = 0;
		cerr << '{';
		for (auto &&i : v)
			cerr << (f++ ? "," : "") << (i ? "T" : "F");
		cerr << "}";
	}
	/* Templates Declarations to support nested datatypes */
	template <typename T>
	void print(T &&x);
	template <typename T>
	void print(vector<vector<T>> mat);
	template <typename T, size_t N, size_t M>
	void print(T (&mat)[N][M]);
	template <typename F, typename S>
	void print(pair<F, S> x);
	template <typename T, size_t N>
	struct Tuple;
	template <typename T>
	struct Tuple<T, 1>;
	template <typename... Args>
	void print(tuple<Args...> t);
	template <typename... T>
	void print(priority_queue<T...> pq);
	template <typename T>
	void print(stack<T> st);
	template <typename T>
	void print(queue<T> q);
	/* Template Datatypes Definitions */
	template <typename T>
	void print(T &&x)
	{
		/*  This works for every container that supports range-based loop
			i.e. vector, set, map, oset, omap, dequeue */
		int f = 0;
		cerr << '{';
		for (auto &&i : x)
			cerr << (f++ ? "," : ""), print(i);
		cerr << "}";
	}
	template <typename T>
	void print(vector<vector<T>> mat)
	{
		int f = 0;
		cerr << "\n~~~~~\n";
		for (auto &&i : mat)
		{
			cerr << setw(2) << left << f++, print(i), cerr << "\n";
		}
		cerr << "~~~~~\n";
	}
	template <typename T, size_t N, size_t M>
	void print(T (&mat)[N][M])
	{
		int f = 0;
		cerr << "\n~~~~~\n";
		for (auto &&i : mat)
		{
			cerr << setw(2) << left << f++, print(i), cerr << "\n";
		}
		cerr << "~~~~~\n";
	}
	template <typename F, typename S>
	void print(pair<F, S> x)
	{
		cerr << '(';
		print(x.first);
		cerr << ',';
		print(x.second);
		cerr << ')';
	}
	template <typename T, size_t N>
	struct Tuple
	{
		static void printTuple(T t)
		{
			Tuple<T, N - 1>::printTuple(t);
			cerr << ",", print(get<N - 1>(t));
		}
	};
	template <typename T>
	struct Tuple<T, 1>
	{
		static void printTuple(T t) { print(get<0>(t)); }
	};
	template <typename... Args>
	void print(tuple<Args...> t)
	{
		cerr << "(";
		Tuple<decltype(t), sizeof...(Args)>::printTuple(t);
		cerr << ")";
	}
	template <typename... T>
	void print(priority_queue<T...> pq)
	{
		int f = 0;
		cerr << '{';
		while (!pq.empty())
			cerr << (f++ ? "," : ""), print(pq.top()), pq.pop();
		cerr << "}";
	}
	template <typename T>
	void print(stack<T> st)
	{
		int f = 0;
		cerr << '{';
		while (!st.empty())
			cerr << (f++ ? "," : ""), print(st.top()), st.pop();
		cerr << "}";
	}
	template <typename T>
	void print(queue<T> q)
	{
		int f = 0;
		cerr << '{';
		while (!q.empty())
			cerr << (f++ ? "," : ""), print(q.front()), q.pop();
		cerr << "}";
	}
	/* Printer functions */
	void printer(const char *) {} /* Base Recursive */
	template <typename T, typename... V>
	void printer(const char *names, T &&head, V &&...tail)
	{
		/* Using && to capture both lvalues and rvalues */
		int i = 0;
		for (size_t bracket = 0; names[i] != '\0' and (names[i] != ',' or bracket != 0); i++)
			if (names[i] == '(' or names[i] == '<' or names[i] == '{')
				bracket++;
			else if (names[i] == ')' or names[i] == '>' or names[i] == '}')
				bracket--;
		cerr.write(names, i) << " = ";
		print(head);
		if (sizeof...(tail))
			cerr << " ||", printer(names + i + 1, tail...);
		else
			cerr << "]\n";
	}
	/* PrinterArr */
	void printerArr(const char *) {} /* Base Recursive */
	template <typename T, typename... V>
	void printerArr(const char *names, T arr[], size_t N, V... tail)
	{
		size_t ind = 0;
		for (; names[ind] and names[ind] != ','; ind++)
			cerr << names[ind];
		for (ind++; names[ind] and names[ind] != ','; ind++)
			;
		cerr << " = {";
		for (size_t i = 0; i < N; i++)
			cerr << (i ? "," : ""), print(arr[i]);
		cerr << "}";
		if (sizeof...(tail))
			cerr << " ||", printerArr(names + ind + 1, tail...);
		else
			cerr << "]\n";
	}
}
#ifndef ONLINE_JUDGE
#define debug(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printer(#__VA_ARGS__, __VA_ARGS__)
#define debugArr(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printerArr(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...)
#define debugArr(...)
#endif
#define int long long
#define double long double
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define rep(i, a, n) for (int i = (a); i <= (n); ++i)
#define per(i, n, a) for (int i = (n); i >= (a); --i)
int max(int a, int b)
{
	if (a > b)
		return a;
	return b;
}
int min(int a, int b)
{
	if (a < b)
		return a;
	return b;
}
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 1e5 + 10;

double qpow(double a, int b)
{
	double res = 1;
	while (b)
	{
		if (b & 1)
			res = 1.0 * res * a;
		a = 1.0 * a * a;
		b >>= 1;
	}
	return res;
}

int n, l, p;
string s[N];
pii st[N];
int head, tail, sum[N];
double dp[N];
int pre[N];

double calc(int a, int b)
{
	return dp[a] + qpow(abs(sum[b] - sum[a] - l - 1), p);
}

int get(int x, int y)
{
	int l = y, r = n + 1;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (calc(x, mid) >= calc(y, mid))
			r = mid;
		else
			l = mid + 1;
	}
	return r;
}

void dfs(int x)
{
	if (x == 0)
		return;
	dfs(pre[x]);
	rep(i, pre[x] + 1, x - 1) cout << s[i] << ' ';
	cout << s[x] << endl;
}

void solve()
{
	cin >> n >> l >> p;
	rep(i, 1, n)
	{
		cin >> s[i];
		sum[i] = sum[i - 1] + s[i].size() + 1;
	}
	head = tail = 1;
	st[1] = {0, 0};
	rep(i, 1, n)
	{
		while (head < tail && st[head].second <= i)
			head++;
		dp[i] = calc(st[head].first, i);
		pre[i] = st[head].first;
		while (head < tail && st[tail - 1].second >= get(st[tail].first, i))
			tail--;
		st[tail].second = get(st[tail].first, i);
		st[++tail].first = i;
	}
	if (dp[n] > 1e18)
	{
		cout << "Too hard to arrange" << endl;
		cout << "--------------------" << endl;
		return;
	}
	cout << fixed << setprecision(0) << dp[n] << endl;
	// dfs(n);
	cout << "--------------------" << endl;
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	freopen("poet.in","r",stdin);
	freopen("poet.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int testcase = 1;
	cin >> testcase;
	while (testcase--)
		solve();
#ifndef ONLINE_JUDGE
	cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
	cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
	return 0;
}

标签:int,void,tail,cerr,template,print,诗人,NOI2009
From: https://www.cnblogs.com/xiaruize/p/18101835

相关文章

  • 「NOI2009」管道取珠
    妙妙题#dp转换一下\(a_i^2\),发现这个值等价于操作\(2\)次最后得到结果一样的方案数那么这就是容易的了\(dp_{k,i,j}\)表示操作了\(k\)轮,第一次的上面取了\(i\)个,第二次的上面取了\(j\)个转移分\(4\)种暴力就行注意空间限制要滚动//Author:xiaruize#ifndefO......
  • 「NOI2009」植物大战僵尸
    Dinic#网络流#拓扑排序每个点向保护的点建图,对这个图拓扑排序,然后就是求这个图的最大完全子图,就是\(dinic\)板子//Author:xiaruize#ifndefONLINE_JUDGEboolstart_of_memory_use;#else#definedebug(x)#endif#include<bits/stdc++.h>usingnamespacestd;#ifnde......
  • 「NOI2009」变换序列
    二分图最大匹配#贪心如果没有字典序最小的限制,直接二分图最大匹配就可以了考虑怎么让字典序最小倒序匹配左侧节点,对于每个节点,优先尝试字典序较小的方案,用hungary就行另,如果用费用流,需要将斐波那契的第\(10^4\)位作为费用//Author:xiaruize#ifndefONLINE_JUDGEbool......
  • P3200 [HNOI2009] 有趣的数列 题解
    P3200[HNOI2009]有趣的数列感性地,我们认为在按照数值从小到大填数时每个时刻所填的奇数位的个数\(x\)不小于所填偶数位的个数\(y\)。我们考虑如何证明这一点。性质1:每一个偶数位上的数都要大于它前面所有的数。这一点应当是显然的。性质2:每一个偶数位上的数都不小于它的下......
  • 诗人小G和四边形不等式
    对于线性的dp\(f[i]=min(f[j]+val(i,j))\)或者说是大致的转移方程可以写成这样的dp,时间复杂度大概是\(O(n^2)\)能否优化主要取决于\(val(i,j)\)的内容和\(j\)的范围假如\(j\)的范围是一个单调向后移动的窗口,只要\(val(i,j)\)能够用多项式表达出来,那就是可以斜率优化或者单调队......
  • [HNOI2009] 梦幻布丁
    [HNOI2009]梦幻布丁题目描述$n$个布丁摆成一行,进行$m$次操作。每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色。例如,颜色分别为$1,2,2,1$的四个布丁一共有$3$段颜色.输入格式第一行是两个整数,分别表示布丁个数$n$和操作次数$m$。 第......
  • P3202 [HNOI2009] 通往城堡之路
    考虑将每个支撑点都先设成其下限高度,即\(h_i\getsh_1-(i-1)\timesd\),这样就只会提高某些支撑点的高度。显然每次提高的是一个后缀。提高某个后缀的贡献是当前高度低于原先高度的支撑点数量减去当前高度不低于原先高度的支撑点数量。选择贡献最大的后缀直到最后一个支撑点的高......
  • P6109 [Ynoi2009] rprmq1 题解-猫树+Segment Tree Beats
    20231025P6109[Ynoi2009]rprmq1题解-猫树+SegmentTreeBeats不愧是学长出的题。。。让我更深刻地理解了猫树。Statement传送门有一个\(n\timesn\)的矩阵\(a\),初始全是\(0\),有\(m\)次修改操作和\(q\)次查询操作,先进行所有修改操作,然后进行所有查询操作。一次修......
  • ”写诗“是我们每个爱诗人刻在骨子里的优雅
        在袁岳的《黑苹果》一书中,曾提到其实一个人做到聪明容易,一个人做到勇敢不容易,一个人做到有见识不容易,一个人做到富足不容易,但是最不容易的是做到优雅。关于优雅的解释是:它首先是一种样式与仪态,是一种别致的身体语言,要表现出来落在人家眼里的态度、举止;那是一种对待与处......
  • 诗人小G (恶心的四边形不等式证明)
    前言:没有前言(快累死了,不想写)。solution:题目传送门设$f_i$为第$i$句时最小的不协调度。\[f_i=f_j+\left|s_i-s_j+i-j-1-L\right|^P\]\[f_i=f_j+\left|s_i+i-(s_j+j)-(L+1)\right|^P\]令$w_{i,j}=(s_i+i)-(s_j+j)-(L+1)$。\[f_i=f_j+\left|w_{i,j}\righ......