首页 > 其他分享 >「NOI2009」变换序列

「NOI2009」变换序列

时间:2024-03-28 15:36:31浏览次数:23  
标签:变换 void print int edges cerr 序列 NOI2009 dis

二分图最大匹配 #贪心

如果没有字典序最小的限制,直接二分图最大匹配就可以了

考虑怎么让字典序最小

倒序匹配左侧节点,对于每个节点,优先尝试字典序较小的方案,用 hungary 就行

另,如果用费用流,需要将斐波那契的第 \(10^4\) 位作为费用

// 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 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 = 2e4 + 10;

namespace MCMF
{
	const int MAXN = 3e4, MAXM = 3e4, INF = 0x7fffffff;
	int head[MAXN], cnt = 1;
	struct Edge
	{
		int to, w, c, next;
	} edges[MAXM * 2];
	inline void add(int from, int to, int w, int c)
	{
		edges[++cnt] = {to, w, c, head[from]};
		head[from] = cnt;
	}
	inline void addEdge(int from, int to, int w, int c)
	{
		add(from, to, w, c);
		add(to, from, 0, -c);
	}
	int s, t, dis[MAXN], cur[MAXN];
	bool inq[MAXN], vis[MAXN];
	queue<int> Q;
	bool SPFA()
	{
		while (!Q.empty())
			Q.pop();
		copy(head, head + MAXN, cur);
		fill(dis, dis + MAXN, INF);
		dis[s] = 0;
		Q.push(s);
		while (!Q.empty())
		{
			int p = Q.front();
			Q.pop();
			inq[p] = 0;
			for (int e = head[p]; e != 0; e = edges[e].next)
			{
				int to = edges[e].to, vol = edges[e].w;
				if (vol > 0 && dis[to] > dis[p] + edges[e].c)
				{
					dis[to] = dis[p] + edges[e].c;
					if (!inq[to])
					{
						Q.push(to);
						inq[to] = 1;
					}
				}
			}
		}
		return dis[t] != INF;
	}
	int dfs(int p = s, int flow = INF)
	{
		if (p == t)
			return flow;
		vis[p] = 1;
		int rmn = flow;
		for (int eg = cur[p]; eg && rmn; eg = edges[eg].next)
		{
			cur[p] = eg;
			int to = edges[eg].to, vol = edges[eg].w;
			if (vol > 0 && !vis[to] && dis[to] == dis[p] + edges[eg].c)
			{
				int c = dfs(to, min(vol, rmn));
				rmn -= c;
				edges[eg].w -= c;
				edges[eg ^ 1].w += c;
			}
		}
		vis[p] = 0;
		return flow - rmn;
	}
	int maxflow, mincost;
	inline void run(int s, int t)
	{
		MCMF::s = s, MCMF::t = t;
		while (SPFA())
		{
			int flow = dfs();
			maxflow += flow;
			mincost += dis[t] * flow;
		}
	}
} // namespace MCMF

int n;
int a[N];
vector<int> g[N];
bool vis[N];
int mat[N];

bool match(int x)
{
	if (vis[x])
		return false;
	vis[x] = true;
	for (auto v : g[x])
	{
		if (vis[v])
			continue;
		if (!mat[v] || match(mat[v]))
		{
			mat[v] = x;
			mat[x] = v;
			return true;
		}
	}
	return false;
}

void solve()
{
	cin >> n;
	rep(i, 0, n - 1)
	{
		cin >> a[i];
		int p = (i + a[i]) % n, q = (i - a[i] + n) % n;
		if (p > q)
			swap(p, q);
		g[i].push_back(p + n);
		g[i].push_back(q + n);
		debug(g[i]);
	}
	int cnt = 0;
	per(i, n - 1, 0)
	{
		mms(vis, 0);
		cnt += match(i);
		debug(cnt);
	}
	// debug(cnt);
	if (cnt != n)
	{
		cout << "No Answer" << endl;
		return;
	}
	rep(i, 0, n - 1) cout << mat[i] - n << ' ';
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
	freopen("transform.in","r",stdin);
	freopen("transform.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;
}

标签:变换,void,print,int,edges,cerr,序列,NOI2009,dis
From: https://www.cnblogs.com/xiaruize/p/18101832

相关文章

  • Prufer 序列
    以下\(d_i\)表示\(i\)的度数。Prufer序列完成了一个有标号无根树与序列的双射。长度为\(n-2\)的值域\([1,n]\)的序列一一对应一棵\(n\)个点的有标号无根树。构建序列的方式就是每次找编号最小的叶节点,然后把它连接的点加入序列,然后删掉这个叶节点。原因是什么我也不......
  • P5470 [NOI2019]序列 题解
    P5470:NOI2019序列题意:给定两个长度\(n\)的序列\(a,b\)。要求各选出\(k\)个数,使得这\(2k\)个数之和最大,且两个序列选出的数至少有\(l\)个位置相同。\(n\le2\times10^5\)。command_block的题解但是这个貌似有一些小问题,后文有写。算法:模拟费用流。【费用流模......
  • 关联数据和序列化
    由于EFCore会自动修正导航属性,因此在对象图中可能会产生循环引用。例如,加载博客及其关联文章会生成引用文章集合的博客对象。其中每篇文章将返回引用该博客。某些序列化框架不允许使用循环引用。例如,Json.NET在发现循环引用的情况下,会引发以下异常。Newtonsoft.Json.Json......
  • 1.6.1 变换
    我们要想改变物体的位置,现有解决办法是,每一帧改变物体的顶点并且重配置缓冲区从而使物体移动,但是这样太繁琐,更好的解决方式是使用矩阵(Matrix)来更好的变换(Transform)一个物体。一、向量向量是有方向的量,向量有一个方向(Direction)和大小(Magnitude,也叫强度或长度)。......
  • Chronos: 将时间序列作为一种语言进行学习
    这是一篇非常有意思的论文,它将时间序列分块并作为语言模型中的一个token来进行学习,并且得到了很好的效果。Chronos是一个对时间序列数据的概率模型进行预训练的框架,它将这些值标记为与基于transformer的模型(如T5)一起使用。模型将序列的值缩放和量化到一个固定的词汇表,并在通过......
  • ETL工具-nifi干货系列 第四讲 Avro schema 序列化框架
    一、在使用nifi的过程中会使用到遇到avroschema、avrodata、avroReader、avroWriter等,所以本节课和大家一起学习下avro相关知识。 二、什么是AvroApacheAvro是hadoop中的一个子项目,也是一个数据序列化系统,其数据最终以二进制格式,采用行式存储的方式进行存储。三、什么......
  • 常见问题系列(一)对象序列化
    对象序列化是非常常见的技术,序列化为Xml或者Json字符串,这里记录使用微软内置库序列化为Xml遇到的一个问题。原始代码:usingSystem;usingSystem.Collections.Generic;usingSystem.IO;usingSystem.Text;usingSystem.Xml.Serialization;namespaceSerializeObject{......
  • RMI反序列化分析
    RMI介绍RMI全程RemoteMethodInvocation(远程方法引用),RMI有客户端和服务端,还有一个注册中心,在java中客户端可以通过RMI调用服务端的方法,流程图如下:服务端创建RMI后会在RMIRegistry(注册中心)注册,之后客户端都是从注册中心调用方法,RMI分为三个主体部分:Client-客户端:客户端调用......
  • C#JsonConvert.DeserializeObject反序列化与JsonConvert.SerializeObject序列化
    原文链接:https://blog.csdn.net/qq_45451847/article/details/120434797JSONJSON序列化是将对象转换为JSON格式的字符串,而JSON反序列化是将JSON格式的字符串转换为对象。对于JSON大家都了解,JSON是一种轻量级的文本数据交换格式而非编程语言,既然是数据交换格式,那就需要不断的进......
  • php反序列化魔术方法
    目录系列文章1、php面向对象基本概念、类与对象:http://t.csdnimg.cn/5fRcg2、序列化与反序列化基础:http://t.csdnimg.cn/cZOZv一、魔术方法二、__construct()和__destruct()1、__construct() 2、__destruct()三、__sleep()和__weakup()1、__sleep()2、__wakeup()......