题解 混凝土粉末

传送门

考场上分块水过去了

先说分块:块内按y排序,处理边角的时候归并优化一下可以做到 \(O(n\sqrt n)\)

然后正解是树状数组扫描线
树状数组以操作编号为下标,存的是操作的h
每次询问在树状数组上二分找到第一个前缀和 \(\geqslant y\) 的位置

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define fir first
#define sec second
#define make make_pair
#define pb push_back
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF: *p1++)
inline ll read() {
	ll ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, q;

namespace force{
	int tot;
	struct cge{int l, r, x; ll h; inline void build(int a, int b, int c, ll d) {l=a; r=b; x=c; h=d;}}cge[N];
	void solve() {
		ll y;
		for (int i=1,l,r,h,x; i<=q; ++i) {
			if (read()&1) {
				l=read(); r=read(); h=read();
				cge[++tot].build(l, r, i, h);
			}
			else {
				x=read(); y=read();
				ll h=0;
				for (int j=1; j<=tot; ++j) {
					if (cge[j].l<=x&&cge[j].r>=x) {
						h+=cge[j].h;
						if (h>=y) {printf("%d\n", cge[j].x); goto jump;}
					}
				}
				puts("0");
				jump: ;
			}
		}
		exit(0);
	}
}

namespace task1{
	int ans[N], op[N];
	int bel[N], beg[N], len, lim;
	ll tag[N];
	struct cge{int l, r, x; ll h; inline void build(int a, int b, int c, ll d) {l=a; r=b; x=c; h=d;}}cg[N];
	struct que{int x; ll y; inline void build(int a, ll b) {x=a; y=b;}}qu[N];
	struct tpl{int x, rk; ll dlt; tpl(ll c, int a, int b) {x=a; rk=b; dlt=c;}};
	inline bool operator < (tpl a, tpl b) {return a.dlt<b.dlt;}
	vector<tpl> buc[1010];
	void upd(int l, int r, int x, ll h) {
		// cout<<"upd: "<<x<<endl;
		int sid=bel[l], eid=bel[r];
		if (sid==eid) {
			if (!buc[sid].size()) return ;
			for (int i=beg[sid]; i<buc[sid].size(); ++i) {
				if (l<=buc[sid][i].x&&r>=buc[sid][i].x) {
					buc[sid][i].dlt-=h;
					if (buc[sid][i].dlt<=tag[sid]) {
						ans[buc[sid][i].rk]=x;
						swap(buc[sid][beg[sid]], buc[sid][i]);
						++beg[sid];
					}
				}
			}
			stable_sort(buc[sid].begin()+beg[sid], buc[sid].end());
			return ;
		}
		if (buc[sid].size()) {
			for (int i=beg[sid]; i<buc[sid].size(); ++i) {
				if (l<=buc[sid][i].x&&r>=buc[sid][i].x) {
					buc[sid][i].dlt-=h;
					if (buc[sid][i].dlt<=tag[sid]) {
						ans[buc[sid][i].rk]=x;
						swap(buc[sid][beg[sid]], buc[sid][i]);
						++beg[sid];
					}
				}
			}
			stable_sort(buc[sid].begin()+beg[sid], buc[sid].end());
		}
		for (int i=sid+1; i<eid; ++i) if (buc[i].size()) {
			tag[i]+=h;
			for (int j=beg[i]; j<buc[i].size(); ++j) {
				if (buc[i][j].dlt<=tag[i]) ++beg[i], ans[buc[i][j].rk]=x;
				else break;
			}
		}
		if (buc[eid].size()) {
			for (int i=beg[eid]; i<buc[eid].size(); ++i) {
				if (l<=buc[eid][i].x&&r>=buc[eid][i].x) {
					buc[eid][i].dlt-=h;
					if (buc[eid][i].dlt<=tag[eid]) {
						ans[buc[eid][i].rk]=x;
						swap(buc[eid][beg[eid]], buc[eid][i]);
						++beg[eid];
					}
				}
			}
			stable_sort(buc[eid].begin()+beg[eid], buc[eid].end());
		}
	}
	void solve() {
		len=sqrt(n);
		for (int i=1; i<=n; ++i) bel[i]=(i-1)/len+1, lim=max(lim, bel[i]);
		ll y;
		for (int i=1,l,r,h,x; i<=q; ++i) {
			if ((op[i]=read())&1) {
				l=read(); r=read(); h=read();
				cg[i].build(l, r, i, h);
			}
			else {
				x=read(); y=read();
				qu[i].build(x, y);
				buc[bel[x]].pb(tpl(y, x, i));
			}
		}
		for (int i=1; i<=lim; ++i) sort(buc[i].begin(), buc[i].end());
		for (int i=1; i<=q; ++i) {
			if (op[i]&1) upd(cg[i].l, cg[i].r, i, cg[i].h);
			else printf("%d\n", ans[i]);
		}
		exit(0);
	}
}

signed main()
{
	freopen("concrete.in", "r", stdin);
	freopen("concrete.out", "w", stdout);
	
	n=read(); q=read();
	if (q<=2000) force::solve();
	else task1::solve();

	return 0;
}
posted @ 2021-11-04 21:37  Administrator-09  阅读(1)  评论(0编辑  收藏  举报