Editorial will be completed soon!!↵
↵
Problem A↵
---------↵
↵
<spoiler summary="Code"> ↵
↵
~~~~~↵
#include<bits/stdc++.h>↵
using namespace std;↵
↵
int main() {↵
int n;↵
cin >> n;↵
bool flag;↵
if(n == 1)↵
{↵
int a, b;↵
cin >> a >> b;↵
if(a == b)↵
flag = 1;↵
else↵
flag = 0;↵
}↵
else if(n == 2)↵
{↵
int a, b, c, d;↵
cin >> a >> b;↵
cin >> c >> d;↵
if(a > b) swap(a, b);↵
if(c > d) swap(c, d);↵
if(b == d && a + c == b)↵
flag = 1;↵
else↵
flag = 0;↵
}↵
else if(n == 3)↵
{↵
int a, b, c, d, e, f;↵
cin >> a >> b;↵
cin >> c >> d;↵
cin >> e >> f;↵
if(a > b) swap(a, b);↵
if(c > d) swap(c, d);↵
if(e > f) swap(e, f);↵
if(b > f) {↵
swap(a, e);↵
swap(b, f);↵
}↵
if(d > f) {↵
swap(c, e);↵
swap(d, f);↵
}↵
flag = 0;↵
if(b == d && b == f && b == a + c + e)↵
flag = 1;↵
↵
if(a == c && b + d == f && a + e == f)↵
flag = 1;↵
if(b == d && a + c == f && b + e == f)↵
flag = 1;↵
if(a == d && a + e == f && b + c == f)↵
flag = 1;↵
if(b == c && b + e == f && a + d == f)↵
flag = 1;↵
}↵
if(flag)↵
cout << "yes\n";↵
else↵
cout << "no\n";↵
return 0;↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
This is an adhoc problem. We just need to consider all the possible cases of joining. Note that we can join 2 rectangles only along their common side lengths, if any. ↵
↵
For n = 1, it is trivial, check if it is a square.↵
↵
For n = 2, only possible way is to join the 2 rectangles.↵
↵
For n = 3, we have two cases. Either join them all linearly, all 3 in a row kind of fashion. Another way is to join the 2 rectangles to form a greater rectangle and then join third one, perpendicularly.↵
↵
For all of the above cases, if it is possible to form a square, the side length of square is the largest length / breadth from rectangles.↵
↵
Problem B↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include<bits/stdc++.h>↵
using namespace std;↵
const int mod = 1e9 + 7;↵
int main() {↵
int l, r;↵
cin >> l >> r;↵
if(l != -r || r % 2)↵
cout << "0";↵
else {↵
long long ans = 1;↵
for(int i = 1; i < r; i += 2)↵
ans = ans * 2 * i % mod;↵
cout << ans;↵
}↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
First of all, g(0) = 0. ↵
↵
Since g(g(x)) = -x then using this condition, g(g(g(0))) = -g(0) if we expand 2 outer g's and g(g(g(0))) = g(0) if we expand 2 inner g's. Thus, if g(0) = -g(0) then g(0) = 0.↵
↵
Now, let g(a) = b then g(b) = g(g(a)) = -a, similarly g(-a) = g(g(b)) = -b and g(-b) = g(g(-a)) = a. Thus we get {a, b, -a, -b}, that is we need to divide the given integers into such groups.↵
↵
Therefore, if r != -l, then answer is zero, as we need both positive and negative of a number. ↵
↵
Also, if r is odd, then answer is zero, as we need to divide into groups with exactly 2 positive and their negative integers.↵
By using combinatorics, we can get the answer as follows:↵
** yet to write further**↵
↵
Problem C↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include <bits/stdc++.h>↵
using namespace std;↵
↵
const int MAXN = 300000;↵
const int MO = 1e9;↵
typedef long long ll;↵
ll n;↵
pair<ll, ll> p[MAXN + 10];↵
↵
bool cmp (pair<ll, ll> a, pair<ll, ll> b) {↵
return a.first * b.second < a.second * b.first;↵
}↵
↵
int main() {↵
↵
scanf("%d", &n);↵
assert(n >= 1 && n <= 300000);↵
for(int i = 0; i < n; i++) {↵
int a, b, c; ↵
scanf("%d%d%d", &a, &b, &c);↵
assert(a >= -MO && a <= MO);↵
assert(b >= -MO && b <= MO);↵
assert(c >= -MO && c <= MO);↵
p[i] = make_pair(a, b);↵
}↵
↵
sort(p, p + n, cmp);↵
↵
ll l = 0, r = 0;↵
ll ans = 0;↵
↵
for(int i = 0; i < n; ++i) {↵
while(cmp(p[l], p[i]))↵
++l; ↵
while(r < n && !cmp(p[i], p[r])) ↵
++r;↵
ans += l * (n - r);↵
}↵
↵
printf("%lld\n", ans);↵
↵
return 0;↵
↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
To find all triangles, we need to find number of ways to select 3 lines such that no 2 of them have same slope.↵
↵
We can do this counting, by sorting all the lines by their slope. Now let the slope of 3 lines that we select be m1, m2 and m3, such that m1 < m2 < m3.↵
↵
So we iterate on the 2nd line, that has slope m2 and for each such line, add the possible ways for selecting m1(<m2) and m3(>m2) ways.↵
↵
Problem D↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include<bits/stdc++.h>↵
using namespace std;↵
↵
#define pb push_back↵
↵
typedef long long ll ;↵
↵
const int mod = 1e9 + 7 ;↵
ll powmod(ll a,ll b) {ll res=1;if(a>=mod)a%=mod;for(;b;b>>=1){if(b&1)res=res*a;if(res>=mod)res%=mod;a=a*a;if(a>=mod)a%=mod;}return res;}↵
↵
const int maxn = 100010;↵
const int inf = INT_MAX;↵
↵
bool p[1000000 + 5];↵
vector<ll> prime;↵
↵
ll f(ll a, ll b, ll n)↵
{↵
ll ret = 1;↵
while(1) {↵
ret = ret * n;↵
if( (a - 1) / ret * ret + ret > b)↵
break;↵
}↵
ret = ret / n;↵
return ret;↵
}↵
int main() {↵
ll n, k;↵
cin >> n >> k;↵
for(int i = 2; i <= 1000; i++) {↵
if(p[i])↵
continue;↵
for(int j = i * i; j <= 1000000; j += i)↵
p[j] = 1;↵
}↵
for(int i = 2; i <= 1000000; i++)↵
if(p[i] == 0)↵
prime.pb(i);↵
ll ans = powmod(n + 1, mod - 2);↵
for(int i = 0; i < prime.size(); i++) {↵
ans = ans * f(n + 1 - k, n + 1, prime[i]);↵
if(ans >= mod)↵
ans %= mod;↵
}↵
cout << ans << endl;↵
return 0;↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
Since C(n, i + 1) = C(n, i) * (n — i) / (i + 1). <br>↵
We can iterate on i from 1 to k, and keep some table to store the prime factorisation of each C(n, i).↵
↵
Then we can know the maximum power of each prime that occured and thus their product will give us the required LCM.<br>↵
Another solution for this problem can be to use a mathematical identity <br>↵
Let X be the required answer, X = lcm { C(n, 0), C(n, 1), ...C(n, k)} % mod <br>↵
then (n + 1) * X = lcm(n+1, n, n — 1, ..., n + 1 — k), <br>↵
for proof of above identity [see this](http://math.stackexchange.com/questions/1442/is-there-a-direct-proof-of-this-lcm-identity)<br>↵
So now all we need is to find the lcm of (n + 1 — k, n + 1 — k + 1, ...n-1, n, n + 1) <br>↵
We can do this by iterating over all the primes and then iterating on powers from 1 till the smallest power that is not divisible is found in this range.↵
↵
Problem E↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include <bits/stdc++.h>↵
#define SZ(X) ((int)(X).size())↵
#define ALL(X) (X).begin(), (X).end()↵
#define REP(I, N) for (int I = 0; I < (N); ++I)↵
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)↵
#define RI(X) scanf("%d", &(X))↵
#define RII(X, Y) scanf("%d%d", &(X), &(Y))↵
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))↵
#define DRI(X) int (X); scanf("%d", &X)↵
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)↵
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)↵
#define RS(X) scanf("%s", (X))↵
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)↵
#define MP make_pair↵
#define PB push_back↵
#define MS0(X) memset((X), 0, sizeof((X)))↵
#define MS1(X) memset((X), -1, sizeof((X)))↵
#define LEN(X) strlen(X)↵
#define PII pair<int,int>↵
#define VI vector<int>↵
#define VPII vector<pair<int,int> >↵
#define PLL pair<long long,long long>↵
#define VPLL vector<pair<long long,long long> >↵
#define F first↵
#define S second↵
typedef long long LL;↵
using namespace std;↵
const int MOD = 1e9+7;↵
const int SIZE = 2e5+10;↵
struct Union_Find{↵
int d[SIZE],num[SIZE];↵
void init(int n){↵
REP(i,n)d[i]=i,num[i]=1;↵
}↵
int find(int x){↵
return (x!=d[x])?(d[x]=find(d[x])):x;↵
}↵
bool uu(int x,int y){↵
x=find(x);↵
y=find(y);↵
if(x==y)return 0;↵
if(num[x]>num[y])swap(x,y);↵
num[y]+=num[x];↵
d[x]=y;↵
return 1;↵
}↵
}U;↵
int n,m;↵
struct EDGE{↵
int u,v,a,b;↵
EDGE(int _u=0,int _v=0,int _a=0,int _b=0):u(_u),v(_v),a(_a),b(_b){}↵
bool operator<(const EDGE& e2){return a<e2.a;}↵
}e[SIZE];↵
struct data{↵
int x,y;↵
LL v;↵
data(int _x=0,int _y=0,LL _v=0):x(_x),y(_y),v(_v){}↵
bool operator<(const data& b)const{↵
return v<b.v;↵
}↵
}e2[SIZE];↵
LL mst(LL x){↵
REP(i,m){↵
e2[i]=data(e[i].u,e[i].v,e[i].a*x+e[i].b);↵
}↵
sort(e2,e2+m);↵
int r=n-1;↵
U.init(n);↵
LL res=0;↵
REP(i,m){↵
if(U.uu(e2[i].x,e2[i].y)){↵
r--;↵
res+=e2[i].v;↵
if(!r)break;↵
}↵
}↵
return res;↵
}↵
int main(){↵
RII(n,m);↵
REP(i,m){↵
RII(e[i].u,e[i].v);↵
e[i].u--;e[i].v--;↵
RII(e[i].a,e[i].b);↵
}↵
int ll=-100000000,rr=100000000;↵
LL ma;↵
while(ll<rr){↵
int mm1=ll+(rr-ll)/2;↵
int mm2=mm1+1;↵
LL v1=mst(mm1);↵
LL v2=mst(mm2);↵
ma=max(v1,v2);↵
if(v1<v2)ll=mm2;↵
else rr=mm1;↵
}↵
int med=ll;↵
DRI(Q);↵
while(Q--){↵
DRII(t1,t2);↵
if(t1<=med&&med<=t2)printf("%I64d\n",ma);↵
else if(med<=t1)printf("%I64d\n",mst(t1));↵
else printf("%I64d\n",mst(t2));↵
}↵
return 0;↵
}↵
↵
~~~~~↵
↵
↵
</spoiler>↵
↵
A suboptimal solution first.↵
↵
Let us first look at the algorithm for finding Minimum Spanning tree. <br>↵
↵
We may observe that if the ordering of edges, when sorted by weights, does not change, then the minimum spanning tree remains to be unchanged i.e. the edges in MST remain to be same, even if we increase/decrease the edge weights.↵
↵
So, if we considered all the pairs of edges, found the time when their edge weights become equal, then one of the edge weight becomes larger than the other one, forever, as they are linear functions of time. ↵
↵
Of course, in some cases, if they are identical, then always same.↵
↵
Now, sort these O(m^2) times of intersections, we can say that minimum spanning tree between any of the two adjacent times, remains unchanged.<br> Thus we can find the MSTs for each of these times and answer the queries.<br>↵
This will certainly TLE, O(m^3 log n).<br>↵
The optimal solution uses binary search and attains following complexity.<br>↵
precalculation:(O(log 10^8 * m log(m))) <br>↵
each query:O(m log(m))<br>↵
** optimal solution updated ** <br>↵
The sum of edge cost of every possible spaning tree is a linear function for t. So the MST function is a concave function.↵
For solving this problem, we precalculate the highest position of the MST function by ternary search in range [$--$10^8$, $10^8$]. The time complexity is $O(log(10^8) \times m \times log(m))$. After finishing this step, we get the maximum MST value V_{max} where t is in range [$-10^8$, $10^8$] and let such $t$ as $t_{max}$.↵
↵
Let the MST value of $t = x$ is mst(x).↵
↵
For each query, if $T_{i1} \le t_{max} \le T_{i2}$, the answer is $V_{max}$. If $T_{i2} \le t_{max}$, the answer if mst(T_{i2}). Otherwise, the answer is mst(T_{i1}).↵
↵
Problem A↵
---------↵
↵
<spoiler summary="Code"> ↵
↵
~~~~~↵
#include<bits/stdc++.h>↵
using namespace std;↵
↵
int main() {↵
int n;↵
cin >> n;↵
bool flag;↵
if(n == 1)↵
{↵
int a, b;↵
cin >> a >> b;↵
if(a == b)↵
flag = 1;↵
else↵
flag = 0;↵
}↵
else if(n == 2)↵
{↵
int a, b, c, d;↵
cin >> a >> b;↵
cin >> c >> d;↵
if(a > b) swap(a, b);↵
if(c > d) swap(c, d);↵
if(b == d && a + c == b)↵
flag = 1;↵
else↵
flag = 0;↵
}↵
else if(n == 3)↵
{↵
int a, b, c, d, e, f;↵
cin >> a >> b;↵
cin >> c >> d;↵
cin >> e >> f;↵
if(a > b) swap(a, b);↵
if(c > d) swap(c, d);↵
if(e > f) swap(e, f);↵
if(b > f) {↵
swap(a, e);↵
swap(b, f);↵
}↵
if(d > f) {↵
swap(c, e);↵
swap(d, f);↵
}↵
flag = 0;↵
if(b == d && b == f && b == a + c + e)↵
flag = 1;↵
↵
if(a == c && b + d == f && a + e == f)↵
flag = 1;↵
if(b == d && a + c == f && b + e == f)↵
flag = 1;↵
if(a == d && a + e == f && b + c == f)↵
flag = 1;↵
if(b == c && b + e == f && a + d == f)↵
flag = 1;↵
}↵
if(flag)↵
cout << "yes\n";↵
else↵
cout << "no\n";↵
return 0;↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
This is an adhoc problem. We just need to consider all the possible cases of joining. Note that we can join 2 rectangles only along their common side lengths, if any. ↵
↵
For n = 1, it is trivial, check if it is a square.↵
↵
For n = 2, only possible way is to join the 2 rectangles.↵
↵
For n = 3, we have two cases. Either join them all linearly, all 3 in a row kind of fashion. Another way is to join the 2 rectangles to form a greater rectangle and then join third one, perpendicularly.↵
↵
For all of the above cases, if it is possible to form a square, the side length of square is the largest length / breadth from rectangles.↵
↵
Problem B↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include<bits/stdc++.h>↵
using namespace std;↵
const int mod = 1e9 + 7;↵
int main() {↵
int l, r;↵
cin >> l >> r;↵
if(l != -r || r % 2)↵
cout << "0";↵
else {↵
long long ans = 1;↵
for(int i = 1; i < r; i += 2)↵
ans = ans * 2 * i % mod;↵
cout << ans;↵
}↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
First of all, g(0) = 0. ↵
↵
Since g(g(x)) = -x then using this condition, g(g(g(0))) = -g(0) if we expand 2 outer g's and g(g(g(0))) = g(0) if we expand 2 inner g's. Thus, if g(0) = -g(0) then g(0) = 0.↵
↵
Now, let g(a) = b then g(b) = g(g(a)) = -a, similarly g(-a) = g(g(b)) = -b and g(-b) = g(g(-a)) = a. Thus we get {a, b, -a, -b}, that is we need to divide the given integers into such groups.↵
↵
Therefore, if r != -l, then answer is zero, as we need both positive and negative of a number. ↵
↵
Also, if r is odd, then answer is zero, as we need to divide into groups with exactly 2 positive and their negative integers.↵
By using combinatorics, we can get the answer as follows:↵
** yet to write further**↵
↵
Problem C↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include <bits/stdc++.h>↵
using namespace std;↵
↵
const int MAXN = 300000;↵
const int MO = 1e9;↵
typedef long long ll;↵
ll n;↵
pair<ll, ll> p[MAXN + 10];↵
↵
bool cmp (pair<ll, ll> a, pair<ll, ll> b) {↵
return a.first * b.second < a.second * b.first;↵
}↵
↵
int main() {↵
↵
scanf("%d", &n);↵
assert(n >= 1 && n <= 300000);↵
for(int i = 0; i < n; i++) {↵
int a, b, c; ↵
scanf("%d%d%d", &a, &b, &c);↵
assert(a >= -MO && a <= MO);↵
assert(b >= -MO && b <= MO);↵
assert(c >= -MO && c <= MO);↵
p[i] = make_pair(a, b);↵
}↵
↵
sort(p, p + n, cmp);↵
↵
ll l = 0, r = 0;↵
ll ans = 0;↵
↵
for(int i = 0; i < n; ++i) {↵
while(cmp(p[l], p[i]))↵
++l; ↵
while(r < n && !cmp(p[i], p[r])) ↵
++r;↵
ans += l * (n - r);↵
}↵
↵
printf("%lld\n", ans);↵
↵
return 0;↵
↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
To find all triangles, we need to find number of ways to select 3 lines such that no 2 of them have same slope.↵
↵
We can do this counting, by sorting all the lines by their slope. Now let the slope of 3 lines that we select be m1, m2 and m3, such that m1 < m2 < m3.↵
↵
So we iterate on the 2nd line, that has slope m2 and for each such line, add the possible ways for selecting m1(<m2) and m3(>m2) ways.↵
↵
Problem D↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include<bits/stdc++.h>↵
using namespace std;↵
↵
#define pb push_back↵
↵
typedef long long ll ;↵
↵
const int mod = 1e9 + 7 ;↵
ll powmod(ll a,ll b) {ll res=1;if(a>=mod)a%=mod;for(;b;b>>=1){if(b&1)res=res*a;if(res>=mod)res%=mod;a=a*a;if(a>=mod)a%=mod;}return res;}↵
↵
const int maxn = 100010;↵
const int inf = INT_MAX;↵
↵
bool p[1000000 + 5];↵
vector<ll> prime;↵
↵
ll f(ll a, ll b, ll n)↵
{↵
ll ret = 1;↵
while(1) {↵
ret = ret * n;↵
if( (a - 1) / ret * ret + ret > b)↵
break;↵
}↵
ret = ret / n;↵
return ret;↵
}↵
int main() {↵
ll n, k;↵
cin >> n >> k;↵
for(int i = 2; i <= 1000; i++) {↵
if(p[i])↵
continue;↵
for(int j = i * i; j <= 1000000; j += i)↵
p[j] = 1;↵
}↵
for(int i = 2; i <= 1000000; i++)↵
if(p[i] == 0)↵
prime.pb(i);↵
ll ans = powmod(n + 1, mod - 2);↵
for(int i = 0; i < prime.size(); i++) {↵
ans = ans * f(n + 1 - k, n + 1, prime[i]);↵
if(ans >= mod)↵
ans %= mod;↵
}↵
cout << ans << endl;↵
return 0;↵
}↵
~~~~~↵
↵
↵
</spoiler>↵
↵
Since C(n, i + 1) = C(n, i) * (n — i) / (i + 1). <br>↵
We can iterate on i from 1 to k, and keep some table to store the prime factorisation of each C(n, i).↵
↵
Then we can know the maximum power of each prime that occured and thus their product will give us the required LCM.<br>↵
Another solution for this problem can be to use a mathematical identity <br>↵
Let X be the required answer, X = lcm { C(n, 0), C(n, 1), ...C(n, k)} % mod <br>↵
then (n + 1) * X = lcm(n+1, n, n — 1, ..., n + 1 — k), <br>↵
for proof of above identity [see this](http://math.stackexchange.com/questions/1442/is-there-a-direct-proof-of-this-lcm-identity)<br>↵
So now all we need is to find the lcm of (n + 1 — k, n + 1 — k + 1, ...n-1, n, n + 1) <br>↵
We can do this by iterating over all the primes and then iterating on powers from 1 till the smallest power that is not divisible is found in this range.↵
↵
Problem E↵
---------↵
↵
<spoiler summary="Code">↵
↵
~~~~~↵
#include <bits/stdc++.h>↵
#define SZ(X) ((int)(X).size())↵
#define ALL(X) (X).begin(), (X).end()↵
#define REP(I, N) for (int I = 0; I < (N); ++I)↵
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)↵
#define RI(X) scanf("%d", &(X))↵
#define RII(X, Y) scanf("%d%d", &(X), &(Y))↵
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))↵
#define DRI(X) int (X); scanf("%d", &X)↵
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)↵
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)↵
#define RS(X) scanf("%s", (X))↵
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)↵
#define MP make_pair↵
#define PB push_back↵
#define MS0(X) memset((X), 0, sizeof((X)))↵
#define MS1(X) memset((X), -1, sizeof((X)))↵
#define LEN(X) strlen(X)↵
#define PII pair<int,int>↵
#define VI vector<int>↵
#define VPII vector<pair<int,int> >↵
#define PLL pair<long long,long long>↵
#define VPLL vector<pair<long long,long long> >↵
#define F first↵
#define S second↵
typedef long long LL;↵
using namespace std;↵
const int MOD = 1e9+7;↵
const int SIZE = 2e5+10;↵
struct Union_Find{↵
int d[SIZE],num[SIZE];↵
void init(int n){↵
REP(i,n)d[i]=i,num[i]=1;↵
}↵
int find(int x){↵
return (x!=d[x])?(d[x]=find(d[x])):x;↵
}↵
bool uu(int x,int y){↵
x=find(x);↵
y=find(y);↵
if(x==y)return 0;↵
if(num[x]>num[y])swap(x,y);↵
num[y]+=num[x];↵
d[x]=y;↵
return 1;↵
}↵
}U;↵
int n,m;↵
struct EDGE{↵
int u,v,a,b;↵
EDGE(int _u=0,int _v=0,int _a=0,int _b=0):u(_u),v(_v),a(_a),b(_b){}↵
bool operator<(const EDGE& e2){return a<e2.a;}↵
}e[SIZE];↵
struct data{↵
int x,y;↵
LL v;↵
data(int _x=0,int _y=0,LL _v=0):x(_x),y(_y),v(_v){}↵
bool operator<(const data& b)const{↵
return v<b.v;↵
}↵
}e2[SIZE];↵
LL mst(LL x){↵
REP(i,m){↵
e2[i]=data(e[i].u,e[i].v,e[i].a*x+e[i].b);↵
}↵
sort(e2,e2+m);↵
int r=n-1;↵
U.init(n);↵
LL res=0;↵
REP(i,m){↵
if(U.uu(e2[i].x,e2[i].y)){↵
r--;↵
res+=e2[i].v;↵
if(!r)break;↵
}↵
}↵
return res;↵
}↵
int main(){↵
RII(n,m);↵
REP(i,m){↵
RII(e[i].u,e[i].v);↵
e[i].u--;e[i].v--;↵
RII(e[i].a,e[i].b);↵
}↵
int ll=-100000000,rr=100000000;↵
LL ma;↵
while(ll<rr){↵
int mm1=ll+(rr-ll)/2;↵
int mm2=mm1+1;↵
LL v1=mst(mm1);↵
LL v2=mst(mm2);↵
ma=max(v1,v2);↵
if(v1<v2)ll=mm2;↵
else rr=mm1;↵
}↵
int med=ll;↵
DRI(Q);↵
while(Q--){↵
DRII(t1,t2);↵
if(t1<=med&&med<=t2)printf("%I64d\n",ma);↵
else if(med<=t1)printf("%I64d\n",mst(t1));↵
else printf("%I64d\n",mst(t2));↵
}↵
return 0;↵
}↵
↵
~~~~~↵
↵
↵
</spoiler>↵
↵
A suboptimal solution first.↵
↵
Let us first look at the algorithm for finding Minimum Spanning tree. <br>↵
↵
We may observe that if the ordering of edges, when sorted by weights, does not change, then the minimum spanning tree remains to be unchanged i.e. the edges in MST remain to be same, even if we increase/decrease the edge weights.↵
↵
So, if we considered all the pairs of edges, found the time when their edge weights become equal, then one of the edge weight becomes larger than the other one, forever, as they are linear functions of time. ↵
↵
Of course, in some cases, if they are identical, then always same.↵
↵
Now, sort these O(m^2) times of intersections, we can say that minimum spanning tree between any of the two adjacent times, remains unchanged.<br> Thus we can find the MSTs for each of these times and answer the queries.<br>↵
This will certainly TLE, O(m^3 log n).<br>↵
The optimal solution uses binary search and attains following complexity.<br>↵
precalculation:(O(log 10^8 * m log(m))) <br>↵
each query:O(m log(m))<br>↵
** optimal solution updated ** <br>↵
The sum of edge cost of every possible spaning tree is a linear function for t. So the MST function is a concave function.↵
For solving this problem, we precalculate the highest position of the MST function by ternary search in range [
↵
Let the MST value of $t = x$ is mst(x).↵
↵
For each query, if $T_{i1} \le t_{max} \le T_{i2}$, the answer is $V_{max}$. If $T_{i2} \le t_{max}$, the answer if mst(T_{i2}). Otherwise, the answer is mst(T_{i1}).↵