Description:
现在有nn个互不相同的正整数,两两之和共有n∗(n−1)2n∗(n−1)2个和,现在给定这些和,求x1,x2,...xnx1,x2,...xn。
Solution:
我们可以知道x1+x2=x1+x2=最小的数,x1+x3=x1+x3=第二小的数,那么枚举第三小的数,这样的数只有nn个,用查找一个数是否存在即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 3e4 + 5, P = 10007;
int n, m;
char opt[10];
int f[maxn];
namespace lct {
struct node {
int f, spf, ch[2];
} t[maxn];
struct data {
int k, b;
data() {}
data(int _k, int _b) : k(_k), b(_b) {}
data friend operator + (const data &a, const data &b) {
return data(a.k * b.k % P, (a.b * b.k + b.b) % P);
}
} a[maxn], s[maxn];
bool isr(int x) {
return !t[x].f || (t[t[x].f].ch[0] != x && t[t[x].f].ch[1] != x);
}
int wh(int x) {
return x == t[t[x].f].ch[1];
}
void upd(int x) {
s[x] = s[t[x].ch[0]] + a[x] + s[t[x].ch[1]];
}
void rotate(int x) {
int y = t[x].f, z = t[y].f, w = wh(x);
if(!isr(y)) {
t[z].ch[wh(y)] = x;
}
t[x].f = z;
t[t[x].ch[w ^ 1]].f = y;
t[y].ch[w] = t[x].ch[w ^ 1];
t[x].ch[w ^ 1] = y;
t[y].f = x;
upd(y);
upd(x);
}
void splay(int x) {
for(; !isr(x); rotate(x)) {
if(!isr(t[x].f)) {
rotate(wh(x) == wh(t[x].f) ? t[x].f : x);
}
}
}
void access(int x) {
for(int y = 0; x; y = x, x = t[x].f) {
splay(x);
t[x].ch[1] = y;
upd(x);
}
}
int fr(int x) {
access(x);
splay(x);
while(t[x].ch[0]) {
x = t[x].ch[0];
}
return x;
}
void link(int x, int y) {
if(!y) {
return;
}
if(fr(x) == fr(y)) {
access(x);
splay(x);
t[x].spf = y;
} else {
t[x].spf = 0;
access(x);
splay(x);
t[x].f = y;
}
}
void cut(int x, int y) {
if(t[x].spf == y) {
t[x].spf = 0;
} else {
access(x);
splay(x);
t[t[x].ch[0]].f = 0;
t[x].ch[0] = 0;
upd(x);
}
}
void exgcd(int a, int b, int &x, int &y) {
if(!b) {
x = 1;
y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
int query(int x) {
access(x);
splay(x);
data t1 = s[x];
int T = t[fr(x)].spf;
access(T);
splay(T);
data t2 = s[T];
int a, b;
if(t2.k == 1) {
return t2.b ? -1 : -2;
}
if(t2.k == 0) {
return (t1.k * t2.b + t1.b) % P;
}
exgcd(t2.k - 1, P, a, b);
return ((a * -t2.b % P + P) % P * t1.k % P + t1.b) % P;
}
} using lct::a; using lct::s; using lct::t;
int main() {
scanf("%d", &n);
a[0].k = s[0].k = 1;
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d", &a[i].k, &f[i], &a[i].b);
s[i] = a[i];
}
for(int i = 1; i <= n; ++i) {
lct::link(i, f[i]);
}
scanf("%d", &m);
while(m--) {
int x, p, k, b;
scanf("%s", opt);
if(opt[0] == 'A') {
scanf("%d", &x);
printf("%d\n", lct::query(x));
} else {
scanf("%d%d%d%d", &x, &k, &p, &b);
lct::access(x);
lct::splay(x);
a[x] = lct::data(k, b);
lct::upd(x);
int T = x;
while(t[T].ch[0]) {
T = t[T].ch[0];
}
lct::cut(x, f[x]);
lct::link(T, t[T].spf);
f[x] = p;
lct::link(x, f[x]);
}
}
return 0;
}