数据结构 E 开还是关,这是一个问题

E. 开还是关,这是一个问题

本题时间限制为3s

Description

话说有n个开关,编号1n,初始时都是关的,但由于喵呜的贪玩,有一些开关被喵呜给打开了,现在喵呜想要复原这些开关。但喵呜觉得如果只是把开的给关掉就不能显得他有多么的神,于是,他决定每一次就将a,b之间(包括a,b)的开关调到相反的状态(即开变关,关变开),但是经过多次后,他忘了编号为k的开关的状态,他希望你能帮他解决

Input

输入包括多组数据,每组数据第一行是一个整数n(n<=10^6)

接下来一行有n个整数,代表开关的状态,分别用0,1表示(0表关,1表开)

接下来一个整数mm<=10^6

接下来m行,每一行代表一个操作

C a b a b之间的开关调到相反状态

Q k 询问编号为k的开关的状态

Output

对于每组数据的询问,输出一行,用01表示k开关的状态

Sample Input

5

0 0 1 0 0

3

Q 4

C 2 4

Q 4

Sample Output

1


暴力:(时间多)

#include <stdio.h>
int s[1000010];
int main()
{
    int i,m,n,a,b;
    char t[10];
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    scanf("%d",&s[i]);
    scanf("%d%*c",&m);
    while(m--)
    {
        scanf("%s",t);
        if(t[0]=='Q')
        {
            scanf("%d",&a);
            printf("%d\n",s[a]%2);
        }
        else
        {
            scanf("%d%d",&a,&b);
            for(i=a;i<=b;i++)
             s[i]++;
        }
    }
    return 0;
}

树状数组:(貌似时间最短)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
 
const int maxn = 1000010;
 
int tree[maxn];
int n;
 
inline int Lowbit(int x) {
    return x & (-x);
}
 
inline void Update(int pos, int val) {
    while (pos <= n) {
         tree[pos]=(tree[pos] + val)%2;
        pos += Lowbit(pos);
    }
}
 
inline int Query(int x) {
    int sum = 0;
    while (x > 0) {
        sum=(sum + tree[x])%2;
        x -= Lowbit(x);
    }
    return sum;
}
 
int main()
{
    while (~scanf("%d", &n)) 
	{
        memset(tree, 0, sizeof(tree));
		int i,j,x;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&x);
			if(x)
				Update(i,1),Update(i+1,1);
		}
		int m;
		scanf("%d",&m);
		while(m--)
		{
			char s[5];
			scanf("%s",s);
			if(s[0]=='Q')
			{
				scanf("%d",&x);
				printf("%d\n", Query(x)%2);
			}
			else
			{
				int a, b;
				scanf("%d%d", &a, &b);
				Update(b+1 ,1);
				Update(a, 1);
			}
		}
    }
    return 0;
}


线段树:(模版)。。。。其实我套了半天。。。。

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Tree
{
    int l,r,num,num1,lazy;
}tree[6000000];
int a[1000000];
char str[10];
void build(int t,int x,int y)
{
    tree[t].l=x;
    tree[t].r=y;
    tree[t].num1=0;
    if(x==y)
    {
        tree[t].num=a[x];
        return ;
    }
    int mid=(x+y)/2;
    build(2*t+1,x,mid);
    build(2*t+2,mid+1,y);
    tree[t].num=tree[2*t+1].num+tree[2*t+2].num;
}
void add(int t,int x,int y,int val)
{
    int l=tree[t].l;
    int r=tree[t].r;
    if(l==x&&y==r)
    {
        tree[t].lazy=1;
        tree[t].num1+=val;
        tree[t].num+=val*(l-r+1);
        return ;
    }
    int mid=(l+r)/2;
    if(tree[t].lazy==1)
    {
        tree[t].lazy=0;
        add(2*t+1,l,mid,tree[t].num1);
        add(2*t+2,mid+1,r,tree[t].num1);
        tree[t].num1=0;
    }
    if(x<=mid) add(2*t+1,x,min(y,mid),val);
    if(y>mid) add(2*t+2,max(mid+1,x),y,val);
    tree[t].num=tree[2*t+1].num+tree[2*t+2].num;
}
int query(int t,int x,int y)
{
    int l,r,mid,ans;
    l=tree[t].l;
    r=tree[t].r;
    if(l==x&&y==r)
    {
        return tree[t].num;
    }
    mid=(l+r)/2;
    if(tree[t].lazy==1)
    {
        tree[t].lazy=0;
        add(2*y+1,l,mid,tree[t].num1);
        add(2*t+2,mid+1,r,tree[t].num1);
        tree[t].num1=0;
    }
    ans=0;
    if(x<=mid) ans+=query(2*t+1,x,min(mid,y));
    if(y>mid) ans+=query(2*t+2,max(mid+1,x),y);
    return ans;
}
int main()
{
    int m,n,t,b;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    scanf("%d",&a[i]);
    build(0,0,m-1);
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",str);
        if(str[0]=='Q')
        {
            scanf("%d",&t);
            printf("%d\n",query(0,t-1,t-1)%2);
        }
        else
        {
            scanf("%d%d",&t,&b);
            add(0,t-1,b-1,1);
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值