传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2527
【题解】
整体二分思想,其实就是把一坨二分拿一起处理了。。。
(事实上这题暴力好像。。不需要二分?)
我们定义solve(l,r,al,ar)为当前二分区间为[l,r],在这个区间的公司为id[al..ar]
那么我们每次把l..mid的操作做一下,然后依次判断每个公司是否满足了条件,满足就说明答案在[l,mid],归到左半区间;否则就说明答案在[mid+1,r],归到右半区间。
归到某个区间实际上就是给al...ar重标号,使得有amid,al...amid被划分到左边,amid+1...ar被划分到右边。
递归solve(l,mid,al,amid),solve(mid+1,r,amid+1,ar)即可。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 3e5 + 10; const int mod = 1e9+7; const int INF = 1e9; # define RG register # define ST static int n, m, Q; int bel[M]; struct quest { int L, R, A; quest() {} quest(int L, int R, int A) : L(L), R(R), A(A) {} }q[M]; int head[M], nxt[M], to[M], tot=0; inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } // 区间修改,单点查询 struct BIT { int n; ll c[M << 1]; # define lb(x) (x&(-x)) inline void set(int _n) { n = _n; memset(c, 0, sizeof c); } inline void edt(int x, ll d) { for (; x<=n; x+=lb(x)) c[x] += d; } inline void edt(int x, int y, ll d) { edt(x, d); edt(y+1, -d); } inline ll sum(int x) { ll ret = 0; for (; x; x-=lb(x)) ret += c[x]; return ret; } }T; int a[M]; ll s[M]; int id[M], t1[M], t2[M]; int ans[M]; inline void solve(int l, int r, int al, int ar) { if(al > ar) return; if(l == r) { for (int i=al; i<=ar; ++i) ans[id[i]] = l; return ; } int mid = l+r>>1; for (int i=l; i<=mid; ++i) { if(q[i].L <= q[i].R) T.edt(q[i].L, q[i].R, q[i].A); else T.edt(1, q[i].R, q[i].A), T.edt(q[i].L, m, q[i].A); } ll cur; bool ok; int t1n, t2n, tn; t1n = t2n = 0; for (int i=al; i<=ar; ++i) { int x = id[i]; ok = 0, cur = s[x]; for (int j=head[x]; j; j=nxt[j]) { cur += T.sum(to[j]); if(cur >= a[x]) { ok = 1; break; } } if(ok) t1[++t1n] = x; else t2[++t2n] = x, s[x] = cur; } for (int i=l; i<=mid; ++i) { if(q[i].L <= q[i].R) T.edt(q[i].L, q[i].R, -q[i].A); else T.edt(1, q[i].R, -q[i].A), T.edt(q[i].L, m, -q[i].A); } tn = al-1; for (int i=1; i<=t1n; ++i) id[++tn] = t1[i]; t1n = tn; for (int i=1; i<=t2n; ++i) id[++tn] = t2[i]; solve(l, mid, al, t1n); solve(mid+1, r, t1n+1, ar); } int main() { cin >> n >> m; for (int i=1; i<=m; ++i) { scanf("%d", &bel[i]); add(bel[i], i); } for (int i=1; i<=n; ++i) scanf("%d", &a[i]), id[i] = i; cin >> Q; for (int i=1; i<=Q; ++i) scanf("%d%d%d", &q[i].L, &q[i].R, &q[i].A); q[++Q] = quest(1, m, INF); T.set(m+1); solve(1, Q, 1, n); for (int i=1; i<=n; ++i) if(ans[i] == Q) puts("NIE"); else printf("%d\n", ans[i]); return 0; }
时间: 2024-10-13 02:57:18