比赛传送门
B:
首先不要把题想太复杂了, 只需要维护好几个值就OK了, 首先是5个数组
fa[x] 表示 x 的父亲是谁
son[x] 表示x有说多少个儿子
op[x] 表示x被操作的次数
a[x] 表示x的儿子对x的影响数
b[x] 表示x的孙子对x的影响数
有了这些的基础, 那么对于每次我们操作的点u的点权和res, 首先是他父亲对他的影响 res += a[fa[u]] + op[fa[u]]*2 ; (为什么*2好好想想)
其次:
res += (son[u] + 1) * op[u] + a[u] * 2 + b[u];
son[u] + 1 是指改变点u对它本身和其儿子的影响, 而a[u]表示儿子对它的影响, b[u]表示u的孙子对u的影响.
所以代码如下: (提醒下, 不知道为什么会T, 然后用了fastio, 直接到400ms, 读入挂真的猛)
AC Code
const int maxn = 1e5+5;
int cas=1;
int fa[maxn],son[maxn],op[maxn],a[maxn],b[maxn];
struct FastIO
{
static const int S = 2*100;
int wpos;
char wbuf[S];
FastIO() : wpos(0) {}
inline int xchar()
{
static char buf[S];
static int len = 0, pos = 0;
if (pos==len)
pos = 0, len = fread(buf, 1, S, stdin);
if (pos==len) exit(0);
return buf[pos ++];
}
inline int xint()
{
int s = 1, c = xchar(), x = 0;
while(c<=32) c = xchar();
if(c=='-') s = -1, c = xchar();
for(;'0'<=c && c<='9';c=xchar()) x = x*10+c-'0';
return x * s;
}
~FastIO()
{
if(wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
}io;
void solve()
{
int n,m;
n = io.xint(); m = io.xint();
for(int i=1;iint u; u = io.xint();
fa[i+1] = u;
son[u]++;
}
ll ans = 0;
for(int i=1;i<=m;i++) {
int u; u = io.xint();
op[u] = (op[u] + 1) % mod;
ll res = 0;
if(fa[u]) {
int tmp = fa[u];
a[tmp] = (a[tmp] + 1) % mod;
res = (res + a[tmp] + op[tmp] + op[tmp]) % mod;
}
if(fa[fa[u]]) {
int tmp = fa[fa[u]];
b[tmp] = (b[tmp] + 1) % mod;
res = (res + op[tmp]) % mod;
}
res = (res + (son[u] + 1) * op[u] + a[u] + a[u] + b[u]) % mod;
ans = (ans + res * i % mod ) % mod;
}
cout << ans << endl;
}
D:
其实是一道水题, 想好是排序后对应位置当然可以使答案最优就行了, 然后是赋值, 所以可以直接替换掉前x个最小的(前提是有这么多个)就行了…..
AC Code
const int maxn = 2e5+5;
int cas=1;
int a[maxn],b[maxn];
void solve()
{
int n,x,y;
scanf("%d%d%d",&n,&x,&y);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++) {
scanf("%d",&b[i]);
}
sort(a+1,a+1+n);
sort(b+1,b+1+n);
for(int i=1;i<=n&&i<=x;i++) {
if(a[i]<y) a[i] = y;
}
sort(a+1,a+1+n);
int ans = 0;
for(int i=1;i<=n;i++) {
ans = max(ans,b[i]-a[i]);
}
cout << ans << endl;
}