⌈突刺贯穿第二分块⌋
查看原帖
⌈突刺贯穿第二分块⌋
547908
NightTide楼主2021/11/16 22:33

虚假的突刺贯穿第二分块

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;

inline int qread() {
	register char c = getchar();
	register int x = 0, f = 1;
	while (c < '0' || c > '9') {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		x = (x << 3) + (x << 1) + c - 48;
		c = getchar();
	}
	return x * f;
}

inline int Abs(const int& x) {return (x > 0 ? x : -x);}
inline int Max(const int& x, const int& y) {return (x > y ? x : y);}
inline int Min(const int& x, const int& y) {return (x < y ? x : y);}

//上面都是卡常 

const int S = 317, N = 100405;

int val[N], f[N];
//并查集 
struct DSU {
	int siz[N], rt[N];
	inline int GetRoot(int v) {
		if (f[v] == v) return v;
		return (f[v] = GetRoot(f[v]));
	}
	inline void Merge(int p, int x, int y) {
		if (rt[y]) {
			f[rt[x] + (p - 1) * S] = rt[y] + (p - 1) * S;
		} else {
			rt[y] = rt[x];
			val[rt[y] + (p - 1) * S] = y;
		}
		siz[y] += siz[x]; rt[x] = siz[x] = 0;
	}
}; 
DSU d[S + 5];
int n, m, a[N], pos[N], mx[N], tag[N];

inline void Read() {
	n = qread(); m = qread();
	for (register int i = 1;i <= n;i++) pos[i] = (i - 1) / S + 1, a[i] = qread();
}
//去除L的影响 
inline void Rebuild(int bid) {
	for (register int j = (bid - 1) * S + 1;j <= Min(bid * S, n);j++) {
		a[j] = val[d[bid].GetRoot(j)];
		d[bid].siz[a[j]] = d[bid].rt[a[j]] = 0;
		a[j] -= tag[bid];
	}
	for (register int j = (bid - 1) * S + 1;j <= Min(bid * S, n);j++) f[j] = 0;
	tag[bid] = 0;
}
//块内重构 
inline void Maintain(int bid) {
	mx[bid] = 0;
	for (register int i = (bid - 1) * S + 1;i <= bid * S;i++) {
		mx[bid] = Max(mx[bid], a[i]);
		if (!d[bid].rt[a[i]]) f[i] = i, d[bid].rt[a[i]] = i - (bid - 1) * S, val[i] = a[i];
		else f[i] = d[bid].rt[a[i]] + (bid - 1) * S;
		d[bid].siz[a[i]]++;
	}
}

inline void Prefix() {
	for (register int i = 1;i <= pos[n];i++) Maintain(i);
}
//零散点修改 
inline void Modify(int bl, int l, int r, int x) {
	Rebuild(bl);
	for (register int j = l;j <= r;j++) {
		if (a[j] > x) a[j] -= x;
	}
	Maintain(bl);
}
//整块修改 
inline void ModifyBlk(int bi, int x) {
	if (mx[bi] - tag[bi] >= (x << 1)) {
		for (register int j = tag[bi] + 1;j <= tag[bi] + x;j++) {
			if (d[bi].rt[j]) d[bi].Merge(bi, j, j + x);
		}
		tag[bi] += x;
	} else {
		for (register int j = mx[bi];j > tag[bi] + x;j--) {
			if (d[bi].rt[j]) d[bi].Merge(bi, j, j - x);
		}
		mx[bi] = Min(tag[bi] + x, mx[bi]);
	}
}
//零散点查询 
inline int qryd(int bl, int l, int r, int x) {
	register int ans = 0;
	for (register int j = l;j <= r;j++) {
		if (val[d[bl].GetRoot(j)] - tag[bl] == x) ans++;
	}
	//printf("l=%d,r=%d %d\n", l, r, ans);
	return ans;
}
//整块查询 
inline int qryblk(int bi, int x) {
	//printf("%d %d\n", x + tag[bi], d[bi].siz[x + tag[bi]]);
	if (x + tag[bi] > 100000) return 0;
	return d[bi].siz[x + tag[bi]];
}

inline void Solve() {
	for (register int i = 1;i <= m;i++) {
		register int opt = qread(), l = qread(), r = qread(), x = qread();
		if (opt == 1) {
			register int bl = pos[l], br = pos[r];
			if (bl == br) {
				Modify(bl, l, r, x);
			} else {
				Modify(bl, l, bl * S, x);
				Modify(br, (br - 1) * S + 1, r, x);
				for (register int j = bl + 1;j < br;j++) ModifyBlk(j, x);
			}
		} else {
			register int bl = pos[l], br = pos[r];
			if (bl == br) {
				printf("%d\n", qryd(bl, l, r, x));
			} else {
				register int ans = qryd(bl, l, bl * S, x) + qryd(br, (br - 1) * S + 1, r, x);
				for (register int j = bl + 1;j < br;j++) ans += qryblk(j, x);
				printf("%d\n", ans);
			}
		}
	}
}

int main() {
	Read();
	Prefix();
	Solve();
	return 0;
}

真实的突刺贯穿第二分块

#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//前两行是精髓
#define R register
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+5;
int n,m,a[N];
float x;
static char buf[1000000],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
inline int read()
{
	R int x=0;
	R char a=getchar();
	while (a<'0'||a>'9')  a=getchar();
	while (a>='0'&&a<='9') x=(x<<1)+(x<<3)+(a^48),a=getchar();
	return x;
}
int main()
{
	n=read(); m=read();
	for(int i=1;i<=n;i++) a[i]=read();
	while (m--)
	{
		R int opt,l,r,ans=0;
		opt=read(); l=read(); r=read(); x=read();
		if (opt==1)
			for (R int i=l;i<=r;i++) a[i]-=(a[i]>x)?x:0;
		else
		{
			for (R int i=l;i<=r;i++) ans+=!(a[i]-x);
			printf("%d\n",ans);
		}
	}
	return 0;
}

2021/11/16 22:33
加载中...