题干:

链接:https://ac.nowcoder.com/acm/contest/883/G
来源:牛客网

Summer vacation is coming and Mark has returned home from his university having successfully survived the exam week. Today, he is very bored. So his friend Alice challenges him to play a game with stones which is invented by her. Alice gives Mark N\ N N piles of stones numbered from 1\ 1 1 to N\ N N, and there are aia_iai​ stones in the i\ i i-th pile. The rules of the game are simple: Mark will try to remove all stones. In each move, Mark chooses two different non-empty piles and removes one stone from each of those two piles. Mark can perform any number of moves. If all the piles are empty after some number of moves, Mark wins the game. If he can't make a valid move but not all piles are empty, he loses the game. Obviously, if the total number of stones is odd, then Mark is not able to win the game. So there is an additional rule: if initially, the total number of stones is odd, then Mark removes a single stone from the pile with the fewest stones before starting the game. If there are multiple piles with the smallest number of stones, Mark chooses one among them to remove a stone.

Mark found the optimal strategy for Alice's game very quickly and gets bored again. Also, he noticed that for some configuration of stones there is no way to win. So he challenges you to solve this problem: count the number of integer pairs (l,r) (1≤l<r≤N)(l,r) \ (1 \le l < r \le N)(l,r) (1≤l<r≤N) such that it is possible for Mark to win the game if the game is played using only the piles numbered from l\ l l to r\ r r.

输入描述:

The input contains multiple cases. The first line of the input contains a single positive integer T\ T T, the number of cases.
The first line of each case contains a single integer N (2≤N≤300000)N \ (2 \le N \le 300000)N (2≤N≤300000), the number of piles. The following line contains N\ N N space-separated integers, where the i\ i i-th integer denotes ai (1≤ai≤109)a_i \ (1 \le a_i \le 10^9)ai​ (1≤ai​≤109), the number of stones in the i\ i i-th pile.
It is guaranteed that the sum of N\ N N over all cases does not exceed 1000000\ 1000000 1000000.

输出描述:

For each case, print a single integer on a single line, the number of pairs satisfying the required property.

示例1

输入

复制

2
3
1 1 1
4
1 2 3 4

输出

复制

3
3

题目大意:

给你N堆石子,每堆石子中有a[i]个石子,问多少个石子区间,可以满足:

①石子总和若为偶数,那么可以两两取 来自不同堆的石子各一个,重复操作,直到取完。

②如果为奇数,那么在最多石子的一堆中去掉其中一个,使得石子总和变为偶数,然后进入操作①。

解题报告:

对于一个区间来说,如果最大值大于除它之外其他数的和,就肯定不能清空了,反之,通过归纳证明,一定可以清空。(这一个证明好像是前几天codeforce的一个div2B原题?)

因为这题转化后的题意是这样:求有多少个长度不小于2的连续子序列,使得其中最大元素不大于序列和的1/2。

再转化一下题意:求:区间最大值的两倍 小于等于 区间和的区间个数。

子序列的统计的题,可以考虑分治解决。

首先找到最大值的位置pos,这样的话[L,R]= [L,pos-1] + [pos+1,R] + 跨过pos这个位置的区间个数。不难发现这样分治是正确的。(和第一场那个分治做法差不多啊)

但是注意下一步统计跨过pos这个位置的答案的时候,要枚举那个小区间,好像可以证明均摊复杂度是nlogn的。(我也不会证)

然后比较正确的做法就是枚举这个小区间的每一个位置,然后对前缀和二分(因为前缀和是具有单调性的,而值没有),二分右区间的位置。如果尺取的话复杂度是不一定能保证的,详见下面的代码。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 3e5 + 5;
int lg[MAX],f[MAX][33];
int a[MAX],n,Log[MAX];
ll sum[MAX],ans;
inline void ST() {for(int i = 1; i<=n; i++) f[i][0] = i;for(int x,y,j = 1; (1<<j)<=n; j++) {for(int i = 1; i+(1<<j)-1<=n; i++) {x = f[i][j-1],y = f[i+(1<<j-1)][j-1];if(a[x] > a[y]) f[i][j] = x;else f[i][j] = y;}}
}
inline int gMax(int l,int r) {int k = Log[r-l+1];int x = f[l][k],y = f[r-(1<<k)+1][k];if(a[x] < a[y]) return y;else return x;
}
void solve(int L,int R) {if(L >= R) return ;int pos = gMax(L,R);solve(L,pos-1);solve(pos+1,R);if(pos - L + 1< R - pos + 1) {//如果左边的数字少的话 int r = pos;for(int l = L; l<=pos; l++) {while(r <= R && sum[r] - sum[l-1] < 2*a[pos]) r++;ans += R-r+1;}//     for(int l = pos; l>=L; l--) {
//          while(r >= pos && sum[r] - sum[l-1] >= 2*a[pos]) r--;
//          ans += R-r;
//      }}else {int l = pos;for(int r = R; r>=pos; r--) {while(l>=L && sum[r] - sum[l-1] < 2*a[pos]) l--;ans += l-L+1;}//       for(int r = pos; r<=R; r++) {
//          while(l <= pos && sum[r] - sum[l-1] >= 2*a[pos]) l++;
//          ans += l-L;
//      }}
}
int main()
{for(int i = 2; i<MAX; i++) Log[i] = Log[i>>1]+1;int t;cin>>t;while(t--) {scanf("%d",&n);for(int i = 1; i<=n; i++) scanf("%d",a+i),sum[i] = sum[i-1] + a[i];ST();ans = 0;solve(1,n);printf("%lld\n",ans);}return 0 ;
}

TLE的代码:

分析一下原因,其实思路都是一样的,只是实现的时候他相当于是 先移动左指针,然后看右指针最多移动到那里。我是按照一般的尺取,先移动右指针。这样就有个问题当他是递减区间的时候,我这样相当于还是n^2的复杂度,但是他那样的话虽然看起来也是n^2的复杂度,但是至少对于单减的序列或者单增序列复杂度都没问题。(不过保险起见这题还是写二分比较好吧..最差复杂度保证了O(nlog^2 n))

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 3e5 + 5;
int lg[MAX],f[MAX][33];
int a[MAX],n,Log[MAX];
ll sum[MAX],ans;
inline void ST() {for(int i = 1; i<=n; i++) f[i][0] = i;for(int x,y,j = 1; (1<<j)<=n; j++) {for(int i = 1; i+(1<<j)-1<=n; i++) {x = f[i][j-1],y = f[i+(1<<j-1)][j-1];if(a[x] > a[y]) f[i][j] = x;else f[i][j] = y;}}
}
inline int gMax(int l,int r) {int k = Log[r-l+1];int x = f[l][k],y = f[r-(1<<k)+1][k];if(a[x] < a[y]) return y;else return x;
}
void solve(int L,int R) {if(L >= R) return ;int pos = gMax(L,R);solve(L,pos-1);solve(pos+1,R);if(pos - L + 1< R - pos + 1) {//如果左边的数字少的话 int r = R;for(int l = pos; l>=L; l--) {while(r >= pos && sum[r] - sum[l-1] >= 2*a[pos]) r--;ans += R-r;}}else {int l = L;for(int r = pos; r<=R; r++) {while(l <= pos && sum[r] - sum[l-1] >= 2*a[pos]) l++;ans += l-L;}}
}
int main()
{for(int i = 2; i<MAX; i++) Log[i] = Log[i>>1]+1;int t;cin>>t;while(t--) {scanf("%d",&n);for(int i = 1; i<=n; i++) scanf("%d",a+i),sum[i] = sum[i-1] + a[i];ST();ans = 0;solve(1,n);printf("%lld\n",ans);}return 0 ;
}

咖啡鸡的On代码:(但是并不能看懂 先放着吧)

对于每个数都看把这个数当成最大值得左边界和右边界的和,然后求是否这个区间成立。
但是这里不好统计有多少成立的区间,于是便反向取,即求有多少不满足的区间。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=300005;
ll a[maxn],l[maxn],r[maxn];
int main()
{int t;int n,m;cin>>t;while(t--){cin>>n;ll ans=1LL*n*(n+1)/2;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++){int x=0,y=0;while(i-x-1>=1&&a[i-x-1]+l[x]<a[i]){l[x+1]=l[x]+a[i-x-1];x++;}while(i+y+1<=n&&a[i+y+1]+r[y]<a[i]){r[y+1]=r[y]+a[i+y+1];y++;}for(int j=0;j<=x;j++){while(l[j]+r[y]>=a[i]) y--;ans-=y+1;}}cout<<ans<<endl;}return 0;
}

*【2019牛客暑期多校训练营(第三场)- G】Removing Stones(分治)相关推荐

  1. 2019牛客暑期多校训练营 第三场 I Median

    传送门 链接:https://ac.nowcoder.com/acm/contest/883/I 来源:牛客网 JSB has an integer sequence a1,a2,-,ana_1, a ...

  2. 【2019牛客暑期多校训练营(第二场) - H】Second Large Rectangle(单调栈,全1子矩阵变形)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/H 来源:牛客网 题目描述 Given a N×MN \times MN×M binary matrix. ...

  3. 2019牛客暑期多校训练营(第一场)E-ABBA(dp)

    链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...

  4. 2019牛客暑期多校训练营(第一场)

    传送门 参考资料: [1]:官方题解(提取码:t050 ) [2]:标程(提取码:rvxr ) [3]:牛客题解汇总 A.Equivalent Prefixes(单调栈) •题意 定义两个数组 u,v ...

  5. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  6. 【2019牛客暑期多校训练营(第二场)- E】MAZE(线段树优化dp,dp转矩阵乘法,线段树维护矩阵乘法)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/E?&headNav=acm 来源:牛客网 Given a maze with N rows an ...

  7. 【2019牛客暑期多校训练营(第二场)- F】Partition problem(dfs,均摊时间优化)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/F 来源:牛客网 Given 2N people, you need to assign each of ...

  8. 【2019牛客暑期多校训练营(第二场) - D】Kth Minimum Clique(bfs,tricks)

    题干: 链接:https://ac.nowcoder.com/acm/contest/882/D 来源:牛客网 Given a vertex-weighted graph with N vertice ...

  9. 【2019牛客暑期多校训练营(第一场) - A】Equivalent Prefixes(单调栈,tricks)

    题干: 链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Two arrays u and v each with m distinct elem ...

  10. 【2019牛客暑期多校训练营(第一场) - H】XOR(线性基,期望的线性性)

    题干: 链接:https://ac.nowcoder.com/acm/contest/881/H 来源:牛客网 Bobo has a set A of n integers a1,a2,-,ana1, ...

最新文章

  1. Tcp连接arp协议详解
  2. Centos7 ping不了百度
  3. es6与java的相似度_计算字符串的相似度-两种解法
  4. 谁占用了我的Buffer Pool?
  5. Nacos-环境隔离
  6. 12c 新特性之单表恢复
  7. html纵向滚动特效,带视觉差效果的垂直全屏整页滚动特效
  8. 第五十七期:小型企业将如何从5G中受益
  9. 安装m2eclipse插件
  10. [EasyHexo 专栏] #1 - Markdown 编辑器推荐与语法简介
  11. 流行的 NPM 包依赖关系中存在远程代码执行缺陷
  12. 如何学习一个新的系统
  13. iOS 上的相机捕捉 swift
  14. 【课堂教学/课堂复习/课堂竞赛手段探析】给广大教师推荐一个期末课堂复习的最好办法
  15. 中国人民大学_《组织行为学》_19.冲突:怎样避免组织内耗?
  16. Android项目实战(八):列表右侧边栏拼音展示效果
  17. 解决RestTemplate的No instances available for localhost错误
  18. 洋洋背古诗——寒假版
  19. 第四范式战疫侦察三部曲:追踪、筛查、推演 提升疫情防控能力
  20. nape.dynamics.InteractionFilter

热门文章

  1. jquery动画 -- 1.加载指示器
  2. java指令和javac指令总结
  3. Java学习笔记12——JVM入门
  4. 计算机操作员可以免考自考吗,计算机《职业资格证书》可以免考高
  5. 服务器测试文件怎么创建,如何创建一个“FTPS”模拟服务器以单元测试Java中的文件传输...
  6. redis实现轮询算法_【07期】Redis中是如何实现分布式锁的?
  7. fir fpga 不同截止频率_学习FPGA将来的出路在哪里?
  8. python如何处理数据_python数据处理之如何选取csv文件中某几行的数据
  9. 计算机找不到管理无线网络,电脑wifi密码忘了 并且找不到管理无线网络该怎么处理?...
  10. st-link v2怎么连接_三相交流电源的三角形和星形连接