2022.11.12———多校联测【2022NOIP A层联测26】游寄

\(\text{Preface}\)

意识到我好像很久没写博了于是来写一发🤔

\(\text{Rank 24/76}\)
得分 \(\text{50pts + 40pts + 0pts + 15pts = 105pts}\)

最高分 \(\text{285pts}\)\(\text{wtcl}\)

\(\mathfrak{T1}\ 乘筛积\)

签到题。主要考的是分析时间复杂度。

假设当前询问为 \((p, q)\)。首先翻一眼大样例发现一大片 \(0\),于是就可以先把 \(0\) 的情况排除,也就是对于 \(\gcd(p, q) | C\) 就直接输出 \(0\) 了。

然后剩下的就暴力循环 \(x\) 或者 \(y\),这取决于你 \(p\) 大还是 \(q\) 大,这是个小优化。于是对于每个已知的 \(x\)\(y\)\(\mathcal O(1)\) 算出其对应的 \(y\)\(x\) 即可。

最后记录一下答案,下次再用到的时候不用再重复算了。因为答案只有 \(\mathcal O(Q)\) 个于是开个 map 即可。

T1
#pragma GCC target("sse3", "sse2", "sse")
#pragma GCC target("avx", "sse4", "sse4.1", "sse4.2", "ssse3")
#pragma GCC target("f16c")
#pragma GCC optimize("fast-math")
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <cstdio>
#include <cmath>
#include <map>
#define GMY (520 & 1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 300005
#define SQRT 555
#define P 998244353
#define mod %
using namespace std;
// inline void Fastio_setup() { ios :: sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
namespace Fread  { const int SIZE = (1 << 18); char buf[SIZE], *p1 = buf, *p2 = buf; inline char getchar() {return (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, SIZE, stdin), p1 == p2) ? EOF : *p1++);} }
namespace Fwrite { const int SIZE = (1 << 18); char buf[SIZE], *S = buf, *T = buf+SIZE; inline void flush(){ fwrite(buf, 1, S-buf, stdout), S = buf; }  struct NTR{ ~NTR() { flush(); } }ztr;inline void putchar(char c){ *S++ = c; if(S == T) flush(); } }
#ifdef ONLINE_JUDGE
    #define getchar Fread::getchar
    #define putchar Fwrite::putchar
#endif
namespace Fastio{
    struct Reader{ template <typename T> Reader & operator >> (T & x) {char c = getchar(); bool f = false;while (c < '0' or c > '9') { if (c == '-') f = true;c = getchar();} x = 0;while(c >= '0' and c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} if (f) x = -x;return *this;}Reader&operator>>(char&c){ c=getchar();while(c=='\n'||c==' '||c=='\r')c=getchar();return *this;}Reader&operator>>(char*str){ int len=0;char c=getchar(); while(c=='\n'||c==' '||c=='\r')c=getchar(); while(c!='\n'&&c!=' '&&c!='\r')str[len++]=c,c=getchar(); str[len]='\0'; return *this;}Reader(){}}cin;
    struct Writer{ template <typename T> Writer & operator << (T   x) {if(x == 0) return putchar('0'), *this;if(x < 0) putchar('-'), x = -x;static int sta[45], top = 0; while (x)  sta[++top] = x %10, x /= 10; while (top)  putchar(sta[top] + '0'), --top; return *this;} Writer&operator<<(char c){putchar(c);return*this;}Writer&operator<<(const char*str){int cur=0;while(str[cur])putchar(str[cur++]);return *this;}Writer(){}}cout;
}
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
	还没下载下来
	T2 怎么感觉像是个多重背包的板子?
	等等你这编译选项
	C++17?啥玩意不应该是C++14吗?
	我看accoders让交的就是C++14,那我还是按着C++14的标准写了
*/

/*
	具体来说就是给定你 p、q,对于每一个x让你求 px + qy = C 的y的个数然后乘起来
	(略微思考)
	O(1)或者O(log)的?
	(略微微思考)
	什么玩应 这和exgcd有关是吗
	那首先排除不合法 p和q必须都是C的倍数
	等等 啥玩意
	不是ax + by = C有解当且仅当a和b都是C的倍数吗
	那应该是我记错了
	那难不成是 C要是gcd(a, b)的倍数,才可能有整数解?
	好像是这样
	但是是整数解而不是正数解
	如果我直接考虑的是爆扫
	那就爆扫吧qAq
	
	行
	简单看了一下发现该判0的都给判过去了,现在要优化的就是那个O(nm)爆扫
	
	行给他改成了O(n)计算
	O(Tn)的,问题是当然切不了
	如果pq特殊构造的话,算着大概有40pts的样子
	
	加个没啥用的小优化,如果n>m就枚举y而不是枚举x
	没有这个的样例,可能是对的?
	应该是对的罢
	希望这个交换没问题
	
	不是,什么弔题,正解是相同的就不算了?!?!
*/

int n, m, C;
long long a[N], b[N], tmp[N];

map<int, long long> mp[N];

int gcd(int x, int y) { return ((y == 0) ? (x) : (gcd(y, x%y))); }
inline void Plus(long long& x, long long y) { x += y; if (x >= P) x -= P; }

inline void work() {
	Fastio :: cin >> n >> m >> C;
	for (re i = 1 ; i <= n ; ++ i)
		Fastio :: cin >> a[i];
	for (re i = 1 ; i <= m ; ++ i)
		Fastio :: cin >> b[i];
	
	int Q, p, q, sum; long long final_ans; Fastio :: cin >> Q;
	for (re tms = 1 ; tms <= Q ; ++ tms) {
		// cerr << Q << '\n';
		// cerr << tms;
		Fastio :: cin >> p >> q; final_ans = 0;
		if (C % gcd(p, q) != 0)
			goto OUT;
		if (mp[p].find(q) != mp[p].end())
			{final_ans = mp[p][q]; goto OUT;}
		
		if (p > q) {
			for (re x = 1, y ; x <= n ; ++ x) {
				if (p*x > C)
					break;
				sum = C - p*x;
				if (sum mod q != 0)
					continue;
				y = sum / q;
				Plus(final_ans, a[x] * b[y] mod P);
				/*for (re y = 1 ; y <= m ; ++ y) {
					sum = p*x + q*y;
					if (sum > C)
						break;
					else if (sum == C)
						Plus(final_ans, a[x] * b[y] mod P);
				}*/
			}
		}
		else {
			for (re y = 1, x ; y <= m ; ++ y) {
				if (q*y > C)
					break;
				sum = C - q*y;
				if (sum mod p != 0)
					continue;
				x = sum / p;
				Plus(final_ans, a[x] * b[y] mod P);
				/*for (re y = 1 ; y <= m ; ++ y) {
					sum = p*x + q*y;
					if (sum > C)
						break;
					else if (sum == C)
						Plus(final_ans, a[x] * b[y] mod P);
				}*/
			}
		}
		// DMARK;
		
		mp[p][q] = final_ans;
		
		OUT : {}
		Fastio :: cout << final_ans << '\n';
		// Dl;
	}
}

#undef int
#define IXINGMY
char_phi main() {
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(sedge, sedge);
	#endif
	// Fastio_setup();
	work();
	return GMY;
}

\(\mathfrak{T2}\ 放进去\)

贪心可以水过去。

对于每个超市考虑加或者不加,记 \(cost_k\) 为买 \(k\) 商品的最小花费,于是在考虑每个超市的时候计算一下选某个商品是否更优,更优就计算一下差值 \(cost_k - a_{i, j}\)。当然要考虑赔款的影响,初始化为赔款价格即可。

后来加了一组 \(\text{hack}\) 贪心的数据,shuffle 一下考虑超市的顺序即可。觉得不稳的话可以多跑几遍。

T2
// ubsan: undefined
// accoders
#include <iostream>
#include <cstdio>
#include <random>
#include <algorithm>
#define GMY (520 & 1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 100005
#define M 35
using namespace std;
inline void Fastio_setup() { ios :: sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
	cost[k] 购买k的最小代价
	当买某个商店的总derta小于0的时候就继续买
*/

int n, m;
long long final_ans;
char chs[M];
int p[N];
long long b[M], cost[N];
long long a[N][M];

random_device seed; mt19937 myrand(seed());

inline void work() {
	cin >> n >> m;
	for (re i = 1 ; i <= n ; ++ i)
		for (re j = 1 ; j <= m ; ++ j)
			cin >> a[i][j];
	for (re i = 1 ; i <= m ; ++ i)
		cin >> b[i];
	for (re i = 1 ; i <= m ; ++ i)
		p[i] = i;
	
	for (re i = 1 ; i <= n ; ++ i)
		cost[i] = 1145141919, final_ans += cost[i];
	while (true) {
		shuffle(p+1, p+m+1, myrand);
		long long best = 1145141145141919810, who;
		for (re j = 1 ; j <= m ; ++ j) {// 每个超市
			if (chs[p[j]] == false) {// 尝试加入当前超市
				long long res = b[p[j]];// 首先要买门票
				for (re i = 1 ; i <= n ; ++ i)// 每件商品
					res -= MAX(cost[i]-a[i][p[j]], 0);// 如果在这里买这个商品更优当然就买这个超市的,不优就不变,累计得到的差值
				if (res < best)// 取加入哪个超市代价更小
					best = res, who = p[j];
			}
		}
		if (best <= 0) {// 如果尚能加入新的超市
			final_ans += best, chs[who] = true;
			for (re i = 1 ; i <= n ; ++ i)
				cost[i] = MIN(cost[i], a[i][who]);
		}
		else 
			break;
	}
	
	cout << final_ans << '\n';
}

#undef int
#define IXINGMY
char_phi main() {
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(putin, putin);
	#endif
	Fastio_setup();
	work();
	return GMY;
}

\(\mathfrak{T3}\ 最长路径\)

没改(

\(\mathfrak{T4}\ 生成树的传说\)

赛时就看这个题顺眼,于是赛后改完 \(\text{T1 T2}\) 后直接改这个题。

根据我的理解瞎写点东西

他不是说给定的 \(m\) 条边中前 \(n-1\) 条边是最小生成树的边吗,称这个为树边,其他的称非树边。

对于一个非树边 \((u, v)\),他能影响到的就是在树上 \(u \to v\) 的路径上的边。具体咋影响的就是题解说的那个引理 \(2\)

于是把每个边的取值 \([l, r]\) 进行更新,记非树边 \((u, v)\) 的取值为 \([l_i, r_i]\) 对于路径 \(u \to v\) 上的某一条边 \(e_j\),他的 \(r_j\) 缩小为 \(\min(r_i, r_j)\),而非树边 \((u, v)\)\(l_i\) 缩小为 \(\max(l_i, l_j)\)

剩下的就是确定答案了,把区间 \([l, r]\) 给拍到坐标轴上,于是我们要做的就是要让 \(1 \sim m\) 的每个值都被选上而且边 \(1 \sim m\) 的取值字典序最小。于是对于 \(1 \sim m\) 的每一条边依次确定答案。

套路在坐标轴上对于每个左端点用 vector 存下来他的右端点,对于每一个边二分答案,\(\text{check}\) 是否仍然能让 \(1 \sim m\) 的每个值都被选上。如此确定每一条边的答案即可。

以及在每次确定好当前边的答案之后要更新非树边的 \(l\)。就是题解说的那玩意。

时间复杂度 \(\mathcal O(m^2logm)\)。由于我实现的丑所以我那个好像是 \(\mathcal O(m^2 log^2m)\)\(\text{qAq}\)

代码实现不算很难,但是我写了三百行,不过我猜其中一百行是注释(

不知道时候被卡常了还是 \(\mathcal O(m^2log^2m)\) 本来就过不去,卡在 \(\text{70pts}\) 咋也卡不过去,不想卡了。。

话说我也不知道咋降成 \(\mathcal O(m^2 logm)\),我看鑫队用到了线段树,比较神奇。

其中那个 \(\text{check}\) 可以用 vector 实现,由于我不想每次 \(\text{check}\) 都重新给 vector 赋值于是用了 multiset。好像速度差不多甚至 multiset 还快一点。

T4(删掉一些注释)
// ubsan: undefined
// accoders
// 这题是tm卡常吗
// 我写的应该是O(m^2 logm)的啊
// 这这这这不对吧,我应该写的是题解做法
// tnnd,还不如去改T3,不卡了!
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#define GMY (520 & 1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 3505
#define M 3505
using namespace std;
// inline void Fastio_setup() { ios :: sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
namespace Fread  { const int SIZE = (1 << 18); char buf[SIZE], *p1 = buf, *p2 = buf; inline char getchar() {return (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, SIZE, stdin), p1 == p2) ? EOF : *p1++);} }
namespace Fwrite { const int SIZE = (1 << 18); char buf[SIZE], *S = buf, *T = buf+SIZE; inline void flush(){ fwrite(buf, 1, S-buf, stdout), S = buf; }  struct NTR{ ~NTR() { flush(); } }ztr;inline void putchar(char c){ *S++ = c; if(S == T) flush(); } }
#ifdef ONLINE_JUDGE
    #define getchar Fread::getchar
    #define putchar Fwrite::putchar
#endif
namespace Fastio{
    struct Reader{ template <typename T> Reader & operator >> (T & x) {char c = getchar(); bool f = false;while (c < '0' or c > '9') { if (c == '-') f = true;c = getchar();} x = 0;while(c >= '0' and c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} if (f) x = -x;return *this;}Reader&operator>>(char&c){ c=getchar();while(c=='\n'||c==' '||c=='\r')c=getchar();return *this;}Reader&operator>>(char*str){ int len=0;char c=getchar(); while(c=='\n'||c==' '||c=='\r')c=getchar(); while(c!='\n'&&c!=' '&&c!='\r')str[len++]=c,c=getchar(); str[len]='\0'; return *this;}Reader(){}}cin;
    struct Writer{ template <typename T> Writer & operator << (T   x) {if(x == 0) return putchar('0'), *this;if(x < 0) putchar('-'), x = -x;static int sta[45], top = 0; while (x)  sta[++top] = x %10, x /= 10; while (top)  putchar(sta[top] + '0'), --top; return *this;} Writer&operator<<(char c){putchar(c);return*this;}Writer&operator<<(const char*str){int cur=0;while(str[cur])putchar(str[cur++]);return *this;}Writer(){}}cout;
}
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
	看 wflszhangzeyang 大佬的代码看懂了.jpg
	思路还算明确
	开打吧
*/

int n, m;
int ans[M];
char use[M][M];

struct Edge { int u, v, l, r; };
struct node { int v, id; };

struct Edge e[M];

vector<node> edger[N];

struct GRAPH {
	char dfs(int x, int faer, int target, int root) {
		if (x == target)
			return true;
		for (auto iw : edger[x]) {
			if (iw.v == faer)
				continue;
			if (dfs(iw.v, x, target, root) == true)
				{use[root][iw.id] = true; return true;}
		}
		return false;
	}
};

struct MARGIN {
	int l, r, mid, anser;
	int kl[M], kr[M];
	priority_queue< int, vector<int>, greater<int> > q;
	multiset<int> s[M];
	multiset<int> :: iterator it;
	
	inline char check() {
		for (re i = 1 ; i <= m ; ++ i) {// 值域
			// DMARK;
			for (auto iw : s[i])// 加入右端点
				q.push(iw);
			if (q.empty() == true or q.top() < i)
				{while (q.empty() == false) q.pop(); return false;}
			q.pop();
		}
		return true;
	}
	inline int GetVal(int root) {// 当前点放在哪里
		l = e[root].l, r = e[root].r, anser = e[root].r;
		while (l <= r) {
			mid = ((l + r) >> 1);
			it = s[kl[root]].find(kr[root]); s[kl[root]].erase(it), s[kl[root]].insert(mid); kr[root] = mid;
			(check() == true) ? (r = mid - 1, anser = mid) : (l = mid + 1);
		}
		return anser;
	}
	inline void UpdateVal(int root, int val) {
		it = s[kl[root]].find(kr[root]), s[kl[root]].erase(it), s[val].insert(val);
		ans[root] = e[root].l = e[root].r = kl[root] = kr[root] = val;
		if (root <= n-1)
			for (re i = n ; i <= m ; ++ i)
				if (use[i][root] == true and e[i].l < val+1) {
					it = s[kl[i]].find(kr[i]); s[kl[i]].erase(it), s[val+1].insert(kr[i]);
					e[i].l = kl[i] = val+1;
				}
	}
	inline void Prework() {
		for (re i = 1 ; i <= m ; ++ i)
			kl[i] = e[i].l, kr[i] = e[i].r;
		for (re i = 1 ; i <= m ; ++ i)
			s[kl[i]].insert(kr[i]);
	}
};

struct GRAPH Graph;
struct MARGIN Margin;

inline void work() {
	Fastio :: cin >> n >> m;
	for (re i = 1, uu, vv, li, ri ; i <= m ; ++ i)
		{Fastio :: cin >> uu >> vv >> li >> ri; e[i] = (Edge) { uu, vv, li, ri }; if (i <= n-1) { edger[uu].emplace_back((node) {vv, i}), edger[vv].emplace_back((node) {uu, i}); } }
	
	for (re i = n ; i <= m ; ++ i) {
		char U_L_S = Graph.dfs(e[i].u, e[i].u, e[i].v, i);
		// DMARK;
		for (re j = 1 ; j <= n-1 ; ++ j)
			if (use[i][j] == true)
				e[i].l = MAX(e[i].l, e[j].l), e[j].r = MIN(e[i].r, e[j].r);// 不能把前n-1个边给顶了,同时让前n-1个边的右边界有更多取值
	}
	
	Margin.Prework();
	
	if (Margin.check() == false)
		{Fastio :: cout << -1 << '\n'; return ;}
	
	for (re i = 1 ; i <= m ; ++ i) {
		Margin.UpdateVal(i, Margin.GetVal(i));// 这里比较慢
		Fastio :: cout << ans[i] << _;
	}
	Fastio :: cout << '\n';
}

#undef int
#define IXINGMY
char_phi main() {
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(mst, mst);
	#endif
	// Fastio_setup();
	work();
	return GMY;
}

T4(不删注释)
// ubsan: undefined
// accoders
// 这题是tm卡常吗
// 我写的应该是O(m^2 logm)的啊
// 这这这这不对吧,我应该写的是题解做法
// tnnd,还不如去改T3,不卡了!
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <cstdio>
#include <vector>
#include <queue>
#include <set>
#define GMY (520 & 1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 3505
#define M 3505
using namespace std;
// inline void Fastio_setup() { ios :: sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
namespace Fread  { const int SIZE = (1 << 18); char buf[SIZE], *p1 = buf, *p2 = buf; inline char getchar() {return (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, SIZE, stdin), p1 == p2) ? EOF : *p1++);} }
namespace Fwrite { const int SIZE = (1 << 18); char buf[SIZE], *S = buf, *T = buf+SIZE; inline void flush(){ fwrite(buf, 1, S-buf, stdout), S = buf; }  struct NTR{ ~NTR() { flush(); } }ztr;inline void putchar(char c){ *S++ = c; if(S == T) flush(); } }
#ifdef ONLINE_JUDGE
    #define getchar Fread::getchar
    #define putchar Fwrite::putchar
#endif
namespace Fastio{
    struct Reader{ template <typename T> Reader & operator >> (T & x) {char c = getchar(); bool f = false;while (c < '0' or c > '9') { if (c == '-') f = true;c = getchar();} x = 0;while(c >= '0' and c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} if (f) x = -x;return *this;}Reader&operator>>(char&c){ c=getchar();while(c=='\n'||c==' '||c=='\r')c=getchar();return *this;}Reader&operator>>(char*str){ int len=0;char c=getchar(); while(c=='\n'||c==' '||c=='\r')c=getchar(); while(c!='\n'&&c!=' '&&c!='\r')str[len++]=c,c=getchar(); str[len]='\0'; return *this;}Reader(){}}cin;
    struct Writer{ template <typename T> Writer & operator << (T   x) {if(x == 0) return putchar('0'), *this;if(x < 0) putchar('-'), x = -x;static int sta[45], top = 0; while (x)  sta[++top] = x %10, x /= 10; while (top)  putchar(sta[top] + '0'), --top; return *this;} Writer&operator<<(char c){putchar(c);return*this;}Writer&operator<<(const char*str){int cur=0;while(str[cur])putchar(str[cur++]);return *this;}Writer(){}}cout;
}
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
	看 wflszhangzeyang 大佬的代码看懂了.jpg
	思路还算明确
	开打吧
*/

int n, m;
int ans[M];
char use[M][M];

struct Edge { int u, v, l, r; };
struct node { int v, id; };

struct Edge e[M];

vector<node> edger[N];

struct GRAPH {
	char dfs(int x, int faer, int target, int root) {
		// cerr << x << _ << faer << _ << target << _ << root << '\n';
		if (x == target)
			return true;
		for (auto iw : edger[x]) {
			if (iw.v == faer)
				continue;
			if (dfs(iw.v, x, target, root) == true)
				{use[root][iw.id] = true; return true;}
		}
		return false;
	}
};

struct MARGIN {
	int l, r, mid, anser;
	int kl[M], kr[M];
	// int vec[M][M];
	priority_queue< int, vector<int>, greater<int> > q;
	// vector<int> vec[M];
	multiset<int> s[M];
	multiset<int> :: iterator it;
	
	/*struct Clone {
		int l, r;
		
		friend bool operator < (Clone A, Clone B) { return ((A.l == B.l) ? (A.r < B.r) : (A.l < B.l)); }
	};
	
	struct Clone kl[M];*/
	
	// inline void ClearVector() { for (re i = 1 ; i <= m ; ++ i) vec[i].clear(); }
	// inline void ClearPriorityQueue() { while (q.empty() == false) q.pop(); }
	
	/*inline char check() {
		// ClearVector();
		// for (re i = 1 ; i <= m ; ++ i) vec[i].clear();
		
		/*for (re i = 1 ; i <= m ; ++ i)
			cerr << kl[i] << _ << kr[i] << '\n';
		Dl; Dl;*/
		
		/*for (re i = 1 ; i <= m ; ++ i) {
			if (kl[i] > kr[i])
				return false;
			vec[kl[i]].emplace_back(kr[i]);
		}*/
		/*for (re i = 1 ; i <= m ; ++ i) {// 值域
			// DMARK;
			for (auto iw : vec[i])// 加入右端点
				q.push(iw);
			if (q.empty() == true or q.top() < i)
				{while (q.empty() == false) q.pop(); return false;}
			q.pop();
		}
		return true;
	}
	inline int GetVal(int root) {// 当前点放在哪里
		l = e[root].l, r = e[root].r, anser = e[root].r;
		while (l <= r) {
			mid = ((l + r) >> 1);
			for (re i = 0 ; i < vec[kl[root]].size() ; ++ i)
				if (vec[kl[root]][i] == kr[root])
					{vec[kl[root]][i] = mid; break;}// 可以sort,懒了
			kr[root] = mid;
			(check() == true) ? (r = mid - 1, anser = mid) : (l = mid + 1);
		}
		return anser;
	}
	inline void UpdateVal(int root, int val) {
		ans[root] = e[root].l = e[root].r = kl[root] = kr[root] = val;
		if (root <= n-1)
			for (re i = n ; i <= m ; ++ i)
				if (use[i][root] == true and e[i].l < val) {
					for (re j = 0 ; j < vec[kl[i]].size() ; ++ j)
						if (vec[kl[i]][j] == kr[i])
							{vec[kl[i]][j] = val; break;}// 可以sort,懒了
					e[i].l = kl[i] = val;
				}
	}
	inline void Prework() {
		for (re i = 1 ; i <= m ; ++ i)
			kl[i] = e[i].l, kr[i] = e[i].r;
		for (re i = 1 ; i <= m ; ++ i)
			vec[kl[i]].emplace_back(kr[i]);
	}*/
	inline char check() {
		for (re i = 1 ; i <= m ; ++ i) {// 值域
			// DMARK;
			for (auto iw : s[i])// 加入右端点
				q.push(iw);
			if (q.empty() == true or q.top() < i)
				{while (q.empty() == false) q.pop(); return false;}
			q.pop();
		}
		return true;
	}
	inline int GetVal(int root) {// 当前点放在哪里
		l = e[root].l, r = e[root].r, anser = e[root].r;
		while (l <= r) {
			mid = ((l + r) >> 1);
			it = s[kl[root]].find(kr[root]); s[kl[root]].erase(it), s[kl[root]].insert(mid); kr[root] = mid;
			(check() == true) ? (r = mid - 1, anser = mid) : (l = mid + 1);
		}
		return anser;
	}
	inline void UpdateVal(int root, int val) {
		it = s[kl[root]].find(kr[root]), s[kl[root]].erase(it), s[val].insert(val);
		ans[root] = e[root].l = e[root].r = kl[root] = kr[root] = val;
		if (root <= n-1)
			for (re i = n ; i <= m ; ++ i)
				if (use[i][root] == true and e[i].l < val+1) {
					it = s[kl[i]].find(kr[i]); s[kl[i]].erase(it), s[val+1].insert(kr[i]);
					e[i].l = kl[i] = val+1;
				}
	}
	inline void Prework() {
		for (re i = 1 ; i <= m ; ++ i)
			kl[i] = e[i].l, kr[i] = e[i].r;
		for (re i = 1 ; i <= m ; ++ i)
			s[kl[i]].insert(kr[i]);
	}
	/*inline char check() {
		for (re i = 1 ; i <= m ; ++ i) {
			for (auto iw : s[i])
				q.push(iw);
			if (q.empry() == true or q.top() < i)
				{while (q.empty() == false) q.pop(); return false;}
			q.pop();
		}
		return true;
	}
	inline int GetVal(int root) {
		l = e[root].l, r = e[root].r, anser = e[root].r;
		while (l <= r) {
			mid = ((l + r) >> 1);
			auto it = s[kl[root]].find(kr[root]); s[kl[root]].erase(it), s[kl[root]].insert(mid); kl[root] = mid;
			if (check() == true)
				r = mid - 1, anser = mid;
			else 
				l = mid + 1;
		}
		return anser;
	}
	inline void UpdateVal(int root, int val) {
		ans[root] = kl[root] = kr[root] = e[root].l = e[root].r = val;
	}
	inline void Prework() {
		for (re i = 1 ; i <= m ; ++ i)
			kl[i] = e[i].l, kr[i] = e[i].r;
		for (re i = 1 ; i <= m ; ++ i)
			s[kl[i]].insert(kr[i]);
	}*/
};

struct GRAPH Graph;
struct MARGIN Margin;

inline void work() {
	Fastio :: cin >> n >> m;
	for (re i = 1, uu, vv, li, ri ; i <= m ; ++ i)
		{Fastio :: cin >> uu >> vv >> li >> ri; e[i] = (Edge) { uu, vv, li, ri }; if (i <= n-1) { edger[uu].emplace_back((node) {vv, i}), edger[vv].emplace_back((node) {uu, i}); } }
	
	for (re i = n ; i <= m ; ++ i) {
		char U_L_S = Graph.dfs(e[i].u, e[i].u, e[i].v, i);
		// DMARK;
		for (re j = 1 ; j <= n-1 ; ++ j)
			if (use[i][j] == true)
				e[i].l = MAX(e[i].l, e[j].l), e[j].r = MIN(e[i].r, e[j].r);// 不能把前n-1个边给顶了,同时让前n-1个边的右边界有更多取值
	}
	
	Margin.Prework();
	
	/*for (re i = 1 ; i <= m ; ++ i)
		if (Margin.kl[i] > Margin.kr[i])
			{Fastio :: cout << -1 << '\n'; return ;}*/
	
	if (Margin.check() == false)
		{Fastio :: cout << -1 << '\n'; return ;}
	
	for (re i = 1 ; i <= m ; ++ i) {
		Margin.UpdateVal(i, Margin.GetVal(i));// 这里比较慢
		// cerr << i << '\n';
		Fastio :: cout << ans[i] << _;
	}
	Fastio :: cout << '\n';
}

#undef int
#define IXINGMY
char_phi main() {
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(mst, mst);
	#endif
	// Fastio_setup();
	work();
	return GMY;
}
posted @ 2022-11-12 20:16  char_phi  阅读(4)  评论(2编辑  收藏  举报