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

Preface

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

Rank 24/76
得分 50pts + 40pts + 0pts + 15pts = 105pts

最高分 285ptswtcl

T1 

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

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

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

最后记录一下答案,下次再用到的时候不用再重复算了。因为答案只有 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;
}

T2 

贪心可以水过去。

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

后来加了一组 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;
}

T3 

没改(

T4 

赛时就看这个题顺眼,于是赛后改完 T1 T2 后直接改这个题。

根据我的理解瞎写点东西

他不是说给定的 m 条边中前 n1 条边是最小生成树的边吗,称这个为树边,其他的称非树边。

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

于是把每个边的取值 [l,r] 进行更新,记非树边 (u,v) 的取值为 [li,ri] 对于路径 uv 上的某一条边 ej,他的 rj 缩小为 min(ri,rj),而非树边 (u,v)li 缩小为 max(li,lj)

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

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

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

时间复杂度 O(m2logm)。由于我实现的丑所以我那个好像是 O(m2log2m)qAq

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

不知道时候被卡常了还是 O(m2log2m) 本来就过不去,卡在 70pts 咋也卡不过去,不想卡了。。

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

其中那个 check 可以用 vector 实现,由于我不想每次 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 @   char_phi  阅读(5)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示