心路历程

预计得分:100 + 40 + 30 = 170

实际得分:100 + 30 + 0 = 130

T2有一个部分分的数组没开够RE了。

T3好像是思路有点小问题。。 思路没问题,实现的时候一个细节没想过来。。

Sol

T1

直接把式子化开,发现都可以$O(1)$维护,做完了。。。

#include<cstdio>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const LL MAXN = 1e5 + ;
inline LL read() {
char c = getchar(); LL x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
LL N, a[MAXN], sum, sump;
int main() {
N = read();
for(LL i = ; i <= N; i++) a[i] = read(), sum += a[i], sump += a[i] * a[i];
for(LL i = ; i <= N; i++) {
LL ans = (N - ) * (sump - a[i] * a[i]) - * (sum - a[i]) * (sum - a[i]) + (sum - a[i]) * (sum - a[i]);
if(i != N) printf("%lld ", ans);
else printf("%lld", ans);
}
return ;
}

T1

T2

好难啊,$30$分的枚举颜色dp应该比较好想把,$f[i][j]$表示第$i$个位置,填了$j$个颜色,然后先枚举一下$1$的颜色,前缀和优化一下,$O(n a_i^2)$

正解:

考虑容斥,令$f[i]$表示第$i$个位置的答案

什么都不考虑:$f[i] = f[i - 1] \times a[i]$

这时候会算重第$i$个位置和第$i - 1$个位置相同的情况,减去$f[i-2] * min(a[i], a[i - 1])$

然后会多减去$i - 2, i - 1, i$这三个位置相同的情况,加上$f[i - 3] * min(a[i], a[i  -1], a[i - 2])$

不断容斥下去。

$f[i] = \sum_{j} (-1)^{i - j} f[i - j + 1] * min(a_{(i - j)  \ to \  i})$

但是还有一个问题:这玩意儿是环形的,还需要考虑$1$和$i$不同的情况,。。。

这就很麻烦了,因为$1$和$i$的高度问题很难讨论。

我们直接把序列转一转,令$1$号位置的元素最小,这样$1$号元素不论取什么,$n$号位置一定会少一种取法

考虑如何优化这玩意儿,稍微化简一下,式子就变成了这样(负变正不影响奇偶性)

$f[i] = (-1)^i \sum_{j} (-1)^j f[i - j +1] \times min(a_{(i - j) \  to \  i})$

把$(-1)^j $和$f$看成一项,这东西显然有单调性。

考虑用单调栈去维护

具体做法是:考虑从$i$转移到$i+1$时答案的变化

一种情况是$a[i+1] > a[i]$这时候直接加上$i+1$的贡献即可

另一种情况是$a[i+1] < a[i]$,这时候前面的一些元素对答案的贡献会减小,用单调栈维护,找到第一个小于等于它的,减去这之间的位置的贡献即可。

时间复杂度:$O(n)$

代码中还用到了一个容斥。上面说的dp是不考虑$1$号位置与$i$号位置相同的情况

设$g_i$表示$1$与$i$拼成环相同时的方案数,稍微观察一下不难发现$g_i = f_{i - 1} - g_{i - 1}$。(把$1$和$i$看成相同的元素)

需要注意的是$g_2 = 0$,因此到达$2$时就需要停止

其实这个容斥方法也可以用来求该问题没有$a_i$限制时的通项公式。

代码较为高能,请谨慎查看。。

/*

*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<cmath>
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#define Pair pair<LL, LL>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
//#define LL long long
#define LL long long
#define ull unsigned long long
#define rg register
#define pt(x) printf("%d ", x);
using namespace std;
//using namespace __gnu_pbds;
const LL MAXN = 1e6 + , INF = 1e9 + , mod = 1e9 + ;
const double eps = 1e-;
inline LL read() {
char c = getchar(); LL x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
LL N, a[MAXN], b[MAXN], f[MAXN], top;
Pair s[MAXN];
LL id(LL x) {
return x & ? (-) : ;
}
int main() {
N = read();
LL mn = INF, pos = , cnt = ;
for(LL i = ; i <= N; i++) {
a[i] = read();
if(a[i] < mn) mn = a[i], pos = i;
}
for(LL i = ; i <= N; i++) b[i] = a[pos], pos = pos % N + ;
memcpy(a, b, sizeof(b));
// for(LL i = 1; i <= N; i++) printf("%d ", b[i]);
f[] = -; /*for(LL i = 1; i <= N; i++) {
LL opt = 1, mn = INF;
for(LL j = i; j >= 1; j--) {
mn = min(a[j], mn);
f[i] = (f[i] + opt * f[j - 1] * mn + mod) % mod;
opt = (opt == 1 ? -1 : 1);
}
}*/
LL sum = ; s[++top] = MP(, );LL ans = ;
for(int i = ; i <= N; i++) {
LL now = ;
while(top && a[i] <= s[top].fi) {
sum = (sum - s[top].fi * s[top].se % mod) % mod;
now += s[top].se;
top--;
}
now = (now + f[i - ]) % mod;
//sum += id(i) * a[i] * now;
f[i] = sum + a[i] * now % mod; if(i & ) f[i] = -f[i];
f[i] = (f[i] + mod) % mod; if(i != )
if((N - i) & ) ans = (ans - f[i] + mod) % mod;
else ans = (ans + f[i]) % mod; if((i - ) & ) f[i] = -f[i];
f[i] = (f[i] + mod) % mod; s[++top] = MP(a[i], now);
(sum = sum + now * a[i] % mod + mod) %= mod;
} /*for(int i = N; i >= 2; i--)
if((N - i) & 1) ans = (ans - abs(f[i]) + mod) % mod;
else ans = (ans + abs(f[i])) % mod; */
//for(LL i = 1; i <= N; i++) printf("%I64d\n", f[i]); //puts("");
cout << (ans + mod) % mod;
return ;
}
/*
6
987 654 321 87 54 321 1 10
154 542 12 1 4354 2 12 121 2 45 4
3 5 1 2 4
4 4 4 4 3
3 3 3 2
2 3 1
4
*/

T2

T3

先考虑$m = 0$时。

定义$lowbit(i)$表示$i$的二进制下第一个为$1$的位置,很显然,如果我们把$lowbit(x)$相等的元素全都分给其中一个玩家这样一定是合法的。

每一个$i$能够贡献的数量为$2^{n - i}$。直接对$k$二进制拆分即可。考场上想到了,但是实现的时候傻乎乎的以为每次拆分的时候二进制位不能有重叠。。

$m \not = 0$的时候好像是个神仙dp,明天再看。。咕咕咕

牛客NOIP提高组(二)题解的更多相关文章

  1. 牛客NOIP提高组(三)题解

    心路历程 预计得分:$30 + 0 + 0 = 30$ 实际得分:$0+0+0= 0$ T1算概率的时候没模爆long long了... A 我敢打赌这不是noip难度... 考虑算一个位置的概率,若 ...

  2. 牛客NOIP提高组R1 C保护(主席树)

    题意 题目链接 Sol Orz lyq 我们可以把一支军队(u, v)拆分为两个(u, lca)和(v, lca) 考虑一个点x,什么时候军队对它有贡献,肯定是u或v在他的子树内,且lca在他的子树外 ...

  3. 牛客NOIP提高组R1 A中位数(二分)

    题意 题目链接 Sol 很神仙的题目啊,考场上只会$n^2$的暴力.. 考虑直接二分一个$mid$,我们来判断最终答案是否可能大于$x$. 判断的时候记录一下前缀最小值即可, 设$s[i]$表示$1- ...

  4. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  5. 牛客CSP-S提高组赛前集训营1

    牛客CSP-S提高组赛前集训营1 比赛链接 官方题解 before:T1观察+结论题,T2树形Dp,可以换根或up&down,T3正解妙,转化为图上问题.题目质量不错,但数据太水了~. A-仓 ...

  6. 18/9/16牛客网提高组Day2

    牛客网提高组Day2 T1 方差 第一眼看就知道要打暴力啊,然而并没有想到去化简式子... 可能因为昨晚没睡好,今天上午困死 导致暴力打了一个半小时,还不对... #include <algor ...

  7. 18/9/9牛客网提高组Day1

    牛客网提高组Day1 T1 中位数 这好像是主席树??听说过,不会啊... 最后只打了个暴力,可能是n2logn? 只过了前30%  qwq #include<algorithm> #in ...

  8. 牛客网 提高组第8周 T1 染色

    染色 链接: https://ac.nowcoder.com/acm/contest/176/A 来源:牛客网 题目描述 \(\tt{fizzydavid}\)和\(\tt{leo}\)有\(n\)个 ...

  9. 牛客网 提高组第8周 T2 推箱子 解题报告

    推箱子 链接: https://ac.nowcoder.com/acm/contest/176/B 来源:牛客网 题目描述 在平面上有\(n\)个箱子,每个箱子都可以看成一个矩形,两条边都和坐标轴平行 ...

随机推荐

  1. boobmarklet

    bookmarklet ,一般都称呼为小书签.它是一段 JavaScript 脚本,一般网络上的小书签都是一个链接,它的安装非常简单,只需要把链接拖到你的收藏夹里. 利用它,可以实现一些页面优化.性能 ...

  2. 解决CentOS 7安装zabbix 3.0 无法启动zabbix-server的问题[segfault at 18 ip 00007f78842b4bd0 sp 00007fff1995a818 error 4 in libpthread-2.17.so[7f78842ab000+16000]]

    解决CentOS 7安装zabbix 3.0 无法启动zabbix-server的问题 [root@localhost sbin]# service zabbix-server start Redir ...

  3. AndroidStudio启动时不自动打开项目

    取消勾选Reopen last project on startup选项 点击 OK 就行了

  4. CSharp读取配置文件的类(简单实现)

    Reinventing the wheel 系列 CSharp 读取配置文件的类 简单实现(注意没有写) 本人对CS 不是很熟,库也不熟,所以到网上找个实现,并自己添加了点异常.如果只是读取信息,足够 ...

  5. Java中的数组和方法

    3.1 数组的定义和使用 数组(Array)是用来存储一组相同数据类型数据的集合.数组中的每个数据称为一个元素(element),数组可以分为一维数组,二维数组和多维数组.我们 主要讲解一维数组和二维 ...

  6. 错误:(26, 13) Failed to resolve: com.android.support:appcompat-v7:27.+

    小编也是初学安卓,今天配置环境的时候遇到这个问题了,搞了半天终于找到了问题 在build.gradle中添加 allprojects { repositories { jcenter() maven ...

  7. Spring如何引用properties文件里的…

    [zt]Spring如何引用properties文件里的配置 来自 http://blog.csdn.net/luobo525/archive/2006/11/06/1370258.aspx 1.Pr ...

  8. Jquery.ajax 详细解释 通过Http请求加载远程数据

    首先请看一个Jquery.ajax的例子 $.ajax({ type: "GET", url: "/api/SearchApi/GetResults", dat ...

  9. lung 分割论文

    <4D Lung Tumor Segmentation via Shape Prior and Motion Cues > Abstract— Lung tumor segmentatio ...

  10. 《剑指offer》面试题8—旋转数组的最小数字

    题目:把一个数组最开始的若干个元素搬到数组末尾我们称之为数组的旋转.要求:输入一个递增排序的数组的旋转,输出旋转数组中的最小数字.例如{3,4,5,1,2}是{1,2,3,4,5}的一个旋转,该数组的 ...