制限時間:C / C ++ 1秒、他の言語2秒
スペース制限:C / C ++ 262144K、他の言語524288K
64ビットIO形式:%lld
タイトル説明
図Mのようにエッジがなく、n点の牛肉は、各側に右エッジがあります。wiw_iwi
パスの重みは、このパスに含まれるエッジの重みの最大値であると定義します。
定義d(u、v)は、無向グラフのポイントuからポイントvまでのすべてのパスの中で最小の重みを持つパスの重みを表します
これで、Niuniuは、Lが与えられるたびに、∑i = 1n∑j = i + 1n [d(i、j)≤L] \ sum_ {i = 1} ^ n \ sum_ {jを問い合わせるq回の問い合わせを行います。 = i + 1} ^ n [d(i、j)\ leq L] ∑i = 1n ∑j = i + 1n [d(i、j)≤L]。その中で[C]は、命題Cが真の場合は1を意味し、そうでない場合は0を意味します。たとえば、[質問が非常に弱い] = 1、[1≥2] = 0 [\ text {質問が非常に弱い}] = 1、[1 \ geq 2] = 0 [質問が非常に弱い] = 1、 [1≥2] = 0。
入力が大きくなりすぎないようにするために、プレーヤーは自分のプログラムに入力するすべてのデータを生成する必要があります。次のコードを参照できます。
unsigned int SA, SB, SC; int n, m, q, LIM;
unsigned int rng61(){
SA ^= SA << 16;
SA ^= SA >> 5;
SA ^= SA << 1;
unsigned int t = SA;
SA = SB;
SB = SC;
SC ^= t ^ SA;
return SC;
}
void gen(){
scanf("%d%d%d%u%u%u%d", &n, &m, &q, &SA, &SB, &SC, &LIM);
for(int i = 1; i <= m; i++){
u[i] = rng61() % n + 1;
v[i] = rng61() % n + 1;
w[i] = rng61() % LIM;
}
for(int i = 1; i <= q; i++){
L[i] = rng61() % LIM;
}
}
生成されたui、vi、wiu_i、v_i、w_iui、vi、wiは最初のエッジの属性を表し、LiL_iLiは最初のクエリの入力数を表します。
説明を入力してください:
一行七个正整数
出力の説明:
一行,表示所有答案的异或和。
例1
入る
コピー57 5 480944053 701657892 339027200 10
5 7 5 480944053 701657892 339027200 10
出力
コピー1
1
説明
5つの問い合わせは7、4、0、4、9です。
答えは3、3、1、3、3です
XOR後の答えは1です。
備考:
1≤n≤105,1≤m、q≤5×105,1≤LIM≤1091\ leq n \ leq 10 ^ 5,1 \ leq m、q \ leq 5 \回10 ^ 5,1 \ leq LIM \ leq 10 ^91≤n≤105,1≤m、q≤5×105,1≤LIM≤109
本旨:
すべてのクエリの排他的または合計を出力します。
解決:
まず、MSTは、パスに含まれるエッジの重みの最大値を最小化できます。これは、観察しやすいプロパティであるため、この無向グラフはいくつかのツリーに簡略化されます。すべてのツリーエッジを削除し、小さいものから大きいものへのエッジの重みに従ってそれらを追加し直すと、各エッジの寄与は正確に2つのポイントセットのサイズの積になり、2番目のプロパティも満たすことができるため、MSTを見つけるプロセスで解決できます。すべての質問について、残りの回答は前処理してオフラインで二分することができます。
受け入れられたコード
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 1e5 + 100;
const int M = 5e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }
unsigned int SA, SB, SC; int n, m, q, LIM;
unsigned int rng61(){
SA ^= SA << 16;
SA ^= SA >> 5;
SA ^= SA << 1;
unsigned int t = SA;
SA = SB;
SB = SC;
SC ^= t ^ SA;
return SC;
}
struct node
{
ll w;
int u, v;
bool operator < (const node &oth) const {
return w < oth.w;
}
}a[M];
int f[N], sz[N];
ll val[M], pre[M];
void Init() {
for (int i = 1; i <= n; i++)
f[i] = i, sz[i] = 1;
}
int Find(int x) {
while (x != f[x])
x = f[x];
return x;
}
void Merge(int x, int y) {
x = Find(x);
y = Find(y);
if (x == y)
return;
if (sz[x] > sz[y])
swap(x, y);
f[x] = y, sz[y] += sz[x];
}
int main()
{
sc("%d%d%d%u%u%u%d", &n, &m, &q, &SA, &SB, &SC, &LIM);
Init();
for (int i = 1; i <= m; i++) {
int u = rng61() % n + 1;
int v = rng61() % n + 1;
ll w = rng61() % LIM;
a[i] = { w, u, v };
}
sort(a + 1, a + m + 1);
int k = 0, pos = 0;
for (int i = 1; i <= m; i++) {
if (k == n - 1)
break;
int u = a[i].u, v = a[i].v;
if (Find(u) == Find(v))
continue;
pos++;
pre[pos] = pre[pos - 1] + 1ll * sz[Find(u)] * sz[Find(v)]; // 点对数前缀和
val[pos] = a[i].w;
Merge(u, v);
}
ll ans = 0;
for (int i = 1; i <= q; i++) {
int qi = rng61() % LIM;
int it = upper_bound(val + 1, val + pos + 1, qi) - val; // 二分位置
ans ^= pre[it - 1];
}
printf("%lld\n", ans);
return 0; // 改数组大小!!!用pair记得改宏定义!!!
}