萌新刚学OI,分块10分求助
查看原帖
萌新刚学OI,分块10分求助
109217
天有不测风云楼主2021/4/1 11:27

record

实在是找不出错误来了

#include <iostream>//为了cin、cout
#include <cmath>//为了sqrt
#include <cstdio>//为了getchar、putchar
#define int long long
using namespace std;

long long n, m, x;
bool a[500005]; //灯的原始数组
long long opt, l, r, k;
int id[500005]/*灯所在块*/, b[500005]/*块被反转和*/, s[500005]/*块和*/, len/*块长*/;

inline long long read() { //快读
  long long X=0; bool flag=1; char ch=getchar();
  while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
  while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
  if(flag) return X;
  return ~(X-1);
}

inline void write(int X) {//快写
  if(X<0) {putchar('-'); X=~(X-1);}
  long long s[50],top=0;
  while(X) {s[++top]=X%10; X/=10;}
  if(!top) s[++top]=0;
  while(top) putchar(s[top--]+'0');
  putchar('\n');
  return;
}

void add(int l, int r) { //反转
  int sid = id[l], eid = id[r];//l所在块、r所在块
  if (sid == eid) {//暴力相加
    for (int i = l; i <= r; i++)
      if (!a[i]) a[i] = true, s[sid]++;
      else a[i] = false, s[sid]--;
    return;
  }
  for (int i = l; id[i] == sid; i++)//左边不完整块
    if (!a[i]) a[i] = true, s[sid]++;
    else a[i] = false, s[sid]--;
  for (int i = sid + 1; i < eid; i++) b[i] ++/*块被反转次数++*/, s[i] = len - s[i]/*开灯数=块长-目前开灯数*/;//中间完整块
  for (int i = r; id[i] == eid; i--)//右边不完整块
    if (!a[i]) a[i] = true, s[eid]++;
    else a[i] = false, s[eid]--;
}

long long query(int l, int r) {//求值
  int sid = id[l], eid = id[r];//l所在块、r所在块
  long long ans = 0;
  if (sid == eid) {//暴力求和
    //    cout << 1 << endl;
    for (int i = l; i <= r; i++)
      if (b[sid] % 2 == 0) ans += a[i];
      else ans += !a[i];
    return ans;
  }
  //  cout << 2 << endl;
  for (int i = l; id[i] == sid; i++)//左边不完整块
    if (b[sid] % 2 == 0) ans += a[i];/*如果块被反转次数为偶数,则直接求和*/
    else ans += !a[i];//else 反过来求和
  for (int i = sid + 1; i < eid; i++) ans += s[i];//中间完整块
  for (int i = r; id[i] == eid; i--)//右边不完整块
    if (b[eid] % 2 == 0) ans += a[i];
    else ans += !a[i];
  return ans;
}

signed main() {
  n = read(); m = read();
  len = sqrt(n);
  for (long long i = 1; i <= n; i++) 
    id[i] = (i - 1) / len + 1;
  for (long long i = 1; i <= m; i++) {
    opt = read(); l = read(); r = read();
    opt ? write(query(l, r)) : add(l, r);//opt==0则调用add(),反之调用write()
  }
  return 0;
}
2021/4/1 11:27
加载中...