题目描述:
在太平洋中心有一个圆形小岛,沿着小岛的海岸线分布着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
修改操作:0 x 代表修改公路x,如果公路原来是完好的,则断开,否则修好公路x。
输入格式:
输入第一行为一个整数t,代表下来有t组数据
每组数据输入第一行包含两个整数n,m,分别表示小镇个数和操作命令数目。
输入接下来的m行,每一行代表一条操作指令。
输出格式:
对于相邻两组数据之间要留一空行。
输入样例:
1
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
输出样例:
1
1
1
0
1
0
数据规模:
对于20%的数据满足:1 < = n, m <=1000。
对于40%的数据满足:1 < = n, m <= 100000。
对于100%的数据满足:1 < = n, m <= 500000。
分析
坑爹的输出QAQ 如图所示:
前者是编号,后者是值(道路的状态 0:联通 1:断开)
按题意,其实就是求一段道路的区间和( 但又有些不同,如第二次输出,4->5被封,但可以反向4->3->2->1->5 )
SO,直接用树状数组求区间和(s),与 sum(总和)-s的值,若 二者其一为0,则联通
代码
各种卡常
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
#define close fclose(stdin); fclose(stdout);
using namespace std;
int n,m;
int a[500005],b[500005];
inline int read()
{
int k=1;
int sum=0;
char c=getchar();
for(;'0'>c || c>'9' ;c=getchar())
if(c=='-') k=-1;
for(;'0'<=c && c<='9';c=getchar())
sum=sum*10+c-'0';
return sum*k;
}
inline void write(int x)
{
if(x<0) { putchar('-'); x*=-1; }
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline int abs(int x)
{
return x>0?x:-x;
}
inline int lowbit(int x)
{
return x&(-x);
}
inline void updata(int x,int y)
{
for(;x<=n;x+=lowbit(x))
b[x]+=y;
}
inline int getsum(int x)
{
int sum=0;
for(;x;x-=lowbit(x))
sum+=b[x];
return sum;
}
int main()
{
open("1098");
int T=read();
for(;T;--T)
{
n=read(); m=read();
int sum=0;
for(int i=1;i<=m;++i)
{
int f=read();
if(f)
{
int x=abs(getsum(read()-1)-getsum(read()-1));
//注意取绝对值(顺序问题);
//-1不好解释,看图分析(第i条道路连接i与i+1的点);
//至于read()-1==0的情况,可看样例,不用特殊处理
write((x&&(sum-x))?0:1);
putchar('\n');
}
else
{
int x=read();
updata(x,a[x]?-1:1);
//printf("%d %d\n",x,a[x]?-1:1);
if(a[x]) --sum; else ++sum;
a[x]^=1;
}
}
putchar('\n');
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
}
close;
return 0;
}
关于caioj
哪位dalao可解释一下为何caioj有些题用读优会TLE 无力