hdu 3854 Glorious Array

本文介绍了一道关于数组操作的问题,通过使用树状数组进行优化,解决了数组中节点颜色翻转及查询特定距离对数量的问题。文章详细阐述了解题思路及代码实现。

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

Problem Description
You are given a array with N nodes. The array nodes are numbered from 1 to N ( represented by a_i ). In the start, the color
of any node in the array is white or black. We define that the "distance" between a and b is min{a_i| a<=i<=b} if a-th and bth
nodes have diffrerent color, or infinite if they have the same color.
We will ask you to perfrom some instructions of the following form:
0 i : change the color of the i-th node (from white to black, or from black to white);
or
1 : ask for the kinds of diffrent pair of nodes' distance is less than K
 

Input
The first line contains a positive integer: the number of test cases, at most 100.
After that per test case:
One line with three integers N, m and K (1 ≤ N, m ≤ 1 00000, K ≤ 1000000): the length of the array, the number of
instructions and K which used in operation 1 .
Then comes a line with N intergers a_i (|a_i|<10000000).
A line with N intergers c_i (c_i = 0(white) or 1(black)), which reprsent the color of N nodes.
Next m lines, each will be a instruction described above.
 

Output
one interger for each operation 1.
 

Sample Input
1 5 3 2 2 3 1 4 2 0 1 0 1 1 1 0 2 1
 

Sample Output
5 6

//

题目描述:
给你n个数,和每个数字的状态(0或者1)。
有两种操作:
第一种:翻转某个数字的状态。
第二种:询问,要求输入满足条件的i, j组合个数。
一个满足条件的i,j要求:
A:1 <= i <= j <= n
B: i和j数字的状态不同
C:i和j的闭区间内的数字的最小值小于k(k由输入给定)
解题报告:
对于一开始的输入先求出组合个数。
然后对于每次的翻转状态,更新组合个数:
比如翻转i,如果x[i] < k, 那么只需看i左侧有多少个0或者1(具体看x[i]当前状态),和i右侧有多少个0或者1(同上),就可以知道这次翻转具体变化了多少,具体的实现可以用树状数组。
如果x[i] > k,初始化时记下在i左侧最近的小于k的数字的位置L[i],同理R[i]。
找到L[i]左侧0或者1的个数和R[i]右侧0或者1的个数,就是这次变化的个数。
应该比较好理解。
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define typev int // type of res
#define N 200000
typev ar[N]; // index: 1 ~ N
int lowb(int t) { return t & (-t) ; }
void add(int i, typev v)
{for ( ; i < N; ar[i] += v, i += lowb(i));}
typev sum(int i)
{
    typev s = 0;
    for ( ; i > 0; s += ar[i], i -= lowb(i));
    return s;
}
int n, m, k;
long long nowans;
int x[N], L[N], R[N], sta[N];
void init()
{
    memset(L, -1, sizeof(L)); memset(R, -1, sizeof(R));
    memset(ar, 0, sizeof(ar));
    for(int i = 1; i <= n; i++) if (x[i] < k)
        for(int j = i + 1; j <= n && x[j] >= k; j++)
            L[j] = i;
    for(int i = n; i >= 1; i--) if (x[i] < k)
        for(int j = i - 1; j >= 1 && x[j] >= k; j--)
            R[j] = i;
}
int Get(int l, int r, int now)
{
    //printf("l %d r %d %d %dn", l, r, sum(r), sum(l - 1));
    if (l > r) return 0;
    if (l == -1 || r == -1) return 0;
    if (now == 0) return r - l + 1 - (sum(r) - sum(l - 1));
    return sum(r) - sum(l - 1);
}
int main()
{
    int t;scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= n; i++) scanf("%d", &x[i]);
        init();
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &sta[i]);
            if (sta[i]) add(i, 1);
        }
        nowans = 0;
        for(int i = 1; i <= n; i++)
            if (x[i] < k) nowans += Get(i + 1, n, !sta[i]);
            else nowans += Get(R[i], n, !sta[i]);
        //cout << nowans << endl;
        while(m--)
        {
            int tmp;scanf("%d", &tmp);
            if (tmp == 1) cout << nowans << endl;
            else
            {
                scanf("%d", &tmp);
                int before = 0, after = 0;
                int i = tmp;
                if (x[tmp] < k)
                {
                    before += Get(1, i - 1, !sta[i]) + Get(i + 1, n, !sta[i]);
                    after += Get(1, i - 1, sta[i]) + Get(i + 1, n, sta[i]);
                }else
                {
                    before += Get(1, L[i], !sta[i]) + Get(R[i], n, !sta[i]);
                    after += Get(1, L[i], sta[i]) + Get(R[i], n, sta[i]);
                }
                if (sta[i] == 0) add(i, 1), sta[i] = 1;
                else add(i, -1), sta[i] = 0;
                nowans += (after - before);
            }

        }
    }
    return 0;
}

标题基于SpringBoot+Vue的社区便民服务平台研究AI更换标题第1章引言介绍社区便民服务平台的研究背景、意义,以及基于SpringBoot+Vue技术的研究现状和创新点。1.1研究背景与意义分析社区便民服务的重要性,以及SpringBoot+Vue技术在平台建设中的优势。1.2国内外研究现状概述国内外在社区便民服务平台方面的发展现状。1.3研究方法与创新点阐述本文采用的研究方法和在SpringBoot+Vue技术应用上的创新之处。第2章相关理论介绍SpringBoot和Vue的相关理论基础,以及它们在社区便民服务平台中的应用。2.1SpringBoot技术概述解释SpringBoot的基本概念、特点及其在便民服务平台中的应用价值。2.2Vue技术概述阐述Vue的核心思想、技术特性及其在前端界面开发中的优势。2.3SpringBoot与Vue的整合应用探讨SpringBoot与Vue如何有效整合,以提升社区便民服务平台的性能。第3章平台需求分析与设计分析社区便民服务平台的需求,并基于SpringBoot+Vue技术进行平台设计。3.1需求分析明确平台需满足的功能需求和性能需求。3.2架构设计设计平台的整体架构,包括前后端分离、模块化设计等思想。3.3数据库设计根据平台需求设计合理的数据库结构,包括数据表、字段等。第4章平台实现与关键技术详细阐述基于SpringBoot+Vue的社区便民服务平台的实现过程及关键技术。4.1后端服务实现使用SpringBoot实现后端服务,包括用户管理、服务管理等核心功能。4.2前端界面实现采用Vue技术实现前端界面,提供友好的用户交互体验。4.3前后端交互技术探讨前后端数据交互的方式,如RESTful API、WebSocket等。第5章平台测试与优化对实现的社区便民服务平台进行全面测试,并针对问题进行优化。5.1测试环境与工具介绍测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值