2017年浙江中医药大学大学生程序设计竞赛(重现赛)F - 开心的cc

本文介绍了一个有趣的问题,即分析一个周期性的快乐与不快乐情绪序列,并通过算法确定满足特定条件的日子数量。该算法使用O(n)的时间复杂度,通过维护快乐和不快乐天数来高效解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

CC is a smart girl and she is curious about everything. One day she starts to analyze her lifestyle and finds out that she either feels happy or unhappy in any day, then she collects her mood data and makes numerical representation. She writes down 1 if she is happy, otherwise she writes down 0. 
For example, if CC is happy, happy, unhappy, happy, happy, unhappy in the next 6 days, a numerical sequence which stands for it is 1,1,0,1,1,0

Meanwhile, smart CC finds her mood sequence is always periodic. She also finds the repeated segment like 1,1,0 in the aforementioned example and calls it “feeling repetend”. As a curious girl, CC wants to make another deep analysis. After she gets the length of “feeling repetend” n, she defines a rule: she tries to find a day whose index is d and considers the next d+n-1 days. For each day d' in [d, d+n-1], CC guarantee that the number of happy days is more than unhappy days in [1, d'] days.

Now, CC wonder that how many days which satisfy the rule in n “feeling repetend” days.
 

输入描述:

Input contains multiple test cases.
The first line contains an integer T (1<=T<=20), which is the number of test cases.
Then the first line of each test case contains an integer n (1<=n<=100000), which is the length of “feeling repetend”.
The second line of each test case contains n integers, each integer is either 0 or 1, standing for unhappy or happy.

输出描述:

output a integer represents the answer.
示例1

输入

2
5
1 0 1 1 0
5 
1 1 1 1 1

输出

1
5

说明

For the sample,the days from the third day as a starting point are as follows:
Day1: 1 day happy : 0 days unhappy
Day2: 2 days happy : 0 days unhappy
Day3: 2 days happy : 1 day unhappy
Day4: 3 days happy : 1 day unhappy
Day5: 3 days happy : 2 days unhappy

题解

$O(n)$扫描。

题意比较难懂,而且题意中有描述错的东西,看了样例才渐渐明白。

题意:有一个长度为$2*n$的数组,输入了$a[1]$到$a[n]$,剩下的是前面的拷贝。问有多少个$x$满足$x$属于$[1, n]$,且在区间$[x, x+n-1]$中,$1$的个数大于$0$的个数。

维护两个值,$1$的个数和$0$的个数,每次区间往后面移动一下,两个值更新一下,看有多少符合要求的就可以了。

赛中比较蠢蛋,弄了个前缀和在搞,不过也是可以的。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 200000 + 10;
int T, n;
int a[maxn], sum[maxn];
int m[4 * maxn];

void build(int l, int r, int rt) {
  if(l == r) {
    m[rt] = sum[l];
    return;
  }
  int mid = (l + r) / 2;
  build(l, mid, 2 * rt);
  build(mid + 1, r, 2 * rt + 1);
  m[rt] = min(m[2 * rt], m[2 * rt + 1]);
}

int get(int L, int R, int l, int r, int rt) {
  if(L <= l && r <= R) {
    return m[rt];
  }
  int mid = (l + r) / 2;
  int left = 300000;
  int right = 300000;
  if(L <= mid) left = get(L, R, l, mid, 2 * rt);
  if(R > mid) right = get(L, R, mid + 1, r, 2 * rt + 1);
  return min(left, right);
}

int main() {
  scanf("%d", &T);
  while(T --) {
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) {
      scanf("%d", &a[i]);
      if(a[i] == 0) a[i] --;
      a[n + i] = a[i];
    }
    for(int i = 1; i <= 2 * n; i ++) {
      sum[i] = sum[i - 1] + a[i];
    }
    build(1, 2 * n, 1);
    int ans = 0;
    for(int i = 1; i <= n; i ++) {
      if(get(i, i + n - 1, 1, 2 * n, 1) <= sum[i - 1]) {
        continue;
      }
      ans ++;
    }
    printf("%d\n", ans);
  }
  return 0;
}

  

转载于:https://www.cnblogs.com/zufezzt/p/8080649.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值