树状数组2(破坏公路)

题目描述

     在太平洋中心有一个圆形小岛,沿着小岛的海岸线分布着n个小镇,编号分别为1,2,3~~n;小镇i-1、小镇i、小镇i+1是相邻的(当然小镇n与小镇1相邻)。相邻小镇之间存在一条公路,公路也有编号,公路i连接小镇i和小镇i+1,公路n连接小镇n和小镇1.现在对小岛有m个操作,操作有两种: 
    询问操作:
1 x y 代表小镇x到小镇y是否联通,联通输出1,否则输出
    修改操作:
0 x 代表修改公路x,如果公路原来是完好的,则断开,否则修好公路x 
输入格式
    输入第一行为一个整数t,代表下来有t组数据 
    每组数据输入第一行包含两个整数
nm,分别表示小镇个数和操作命令数目。 
    输入接下来的
m行,每一行代表一条操作指令。 
输出格式
    对于相邻两组数据之间要留一空行。 
输入样例: 

5 10 
1 2 5 
0 4 
1 4 5 
0 2 
1 3 4 
1 1 3 
0 1 
0 2 
1 2 4 
1 2 5 

输出样例: 






数据规模
    对于20%的数据满足:1 < = n, m <=1000 
    对于
40%的数据满足:1 < = n, m <= 100000 

    对于100%的数据满足:1 < = n, m <= 500000

解题思路:这道题目是树状数组的一个小变形。其实与树状数组原版也不没有太大的区别。

代码:(请不要直接拷贝哦)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,m,c[500005];
bool vis[500005];
inline int lowbit(int x)//标配
{
	return x&-x;
}
inline void add(int x,int y)//标配
{
    while(x<=n)
    {
        c[x]=c[x]+y;
        x+=lowbit(x);
    }
}
inline int sum(int x)//标配
{
    int s=0;
    while(x>0)
    {
        s+=c[x];
        x-=lowbit(x);
    }
    return s;
}
int main()
{
    int s,t;
    int x,y,ss;
    scanf("%d",&t);
    while(t--)//输入多组数据
    {
        memset(c,0,sizeof(c));//初始化
        memset(vis,0,sizeof(vis));
        scanf("%d%d",&n,&m);
        for (int i=0;i<m;i++)
        {
            scanf("%d",&s);
            if (s==1)//查询
            {
                scanf("%d%d",&x,&y);
                if (x>y)
                {//交换
                    int tt;
                    tt=x;
                    x=y;
                    y=tt;
                }
                if (sum(y-1)-sum(x-1)==0)
                    printf("1\n"); else 
				if ((sum(x-1)==0)&&(sum(n-1)-sum(y-1)==0)&&(vis[n]==0))
                    printf("1\n"); else
                    printf("0\n");
            }
            else
            {
            	scanf("%d",&x);
                if (vis[x]==1)//这条路是否连上的
                {
                    ss=-1;
                    vis[x]=0;
                }
                else
                {
                    ss=1;
                    vis[x]=1;
                }
                add(x,ss);//改变
            }
        }
        printf("\n");//两个数据间要有空行
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值