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;
}