NC22363. Desperate … Fire Survive
描述
输入描述
The first line contains three integers , the length of the circuitry sequence, the maximal level and the number of queries, respectively.
The second line contains n integers , the levels of nodes in order.
Each of the following q lines contains three integers , describing a query.
Multiple integers in the same line are separated by spaces.
输出描述
Output q lines; each contains one integer, the answer to that query.
示例1
输入:
5 5 5 1 1 1 1 1 1 5 1 1 5 2 1 5 3 1 5 4 1 5 5
输出:
15 10 3 0 0
示例2
输入:
5 5 5 4 3 2 1 1 1 5 1 1 5 2 1 5 3 1 5 4 1 5 5
输出:
9 10 9 6 1
C++14(g++5.4) 解法, 执行用时: 841ms, 内存消耗: 46724K, 提交时间: 2019-12-05 22:31:46
#include<bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define ALL(x) (x).begin(),(x).end() typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const int maxn = 2e5 + 70; const int INF = 0x3f3f3f3f; const ll inf = 0x3f3f3f3f3f3f3f3f; const int MOD = 1e9 + 7; const double eps = 1e-7; const double PI = acos(-1.0); int n, m, q; int a[maxn]; vector<int> V[maxn]; vector<pii> F[maxn]; vector<ll> pre[maxn]; int f(int i, int j){ if(i > n) return n+2; return upper_bound(ALL(F[j]),mp(i,INF))->second; } void add(int j, int e, int x){ if(!F[j].size() || F[j].back().second != x) F[j].pb({e,x}); F[j].back().first = e; } ll calc(int i, int j){ if(!i) return 0; int p = upper_bound(ALL(F[j]),mp(i,INF)) - F[j].begin(); return pre[j][p] - (ll)(F[j][p].first-i-1)*F[j][p].second; } ll query(int l, int r, int k){ if(f(l,k) > r+1) return 0; int L = l, R = r; while(L < R){ int M = L + (R - L + 1)/2; if(f(M,k) > r+1) R = M - 1; else L = M; } L = l; return (ll)(r+2)*(R-L+1) - (calc(R, k) - calc(L - 1, k)); } int main(){ //freopen("in.txt", "r", stdin); while(cin>>n>>m>>q){ for(int i=1;i<=m;i++) V[i].clear(), F[i].clear(), pre[i].clear(); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); V[a[i]].pb(i); } for(int p:V[1]) F[1].pb({p+1, p+1}); if(!F[1].size() || F[1].back().first != n+1) F[1].pb({n+1,n+2}); for(int j=2;j<=m;j++){ int ptr = 0, s = 1; for(int p:V[j]){ while(ptr < F[j-1].size() && F[j-1][ptr].first-1 <= p){ int x = f(F[j-1][ptr].second, j-1); add(j, F[j-1][ptr].first, min(p+1,x)); ptr++; } if(ptr == F[j-1].size()) break; int x = f(F[j-1][ptr].second, j-1); add(j, p+1, min(p+1, x)); if(p+1 == F[j-1][ptr].first) ptr++; } while(ptr < F[j-1].size()){ int x = f(F[j-1][ptr].second, j-1); add(j, F[j-1][ptr].first, x); ptr++; } } /* for(int j=1;j<=m;j++){ cout<<"j: "<<j<<endl; for(int i=0;i<F[j].size();i++){ printf("[%d,%d)=%d ",i?F[j][i-1].first:1,F[j][i].first,F[j][i].second); } printf("\n"); } */ for(int j=1;j<=m;j++){ for(int i=0;i<F[j].size();i++){ if(!i) pre[j].pb((ll)(F[j][i].first-1)*F[j][i].second); else pre[j].pb(pre[j].back()+(ll)(F[j][i].first-F[j][i-1].first)*F[j][i].second); } } while(q--){ int l, r, k; scanf("%d %d %d",&l,&r,&k); ll ans = query(l, r, k); printf("%lld\n", ans); } } return 0; }
C++(clang++11) 解法, 执行用时: 476ms, 内存消耗: 30200K, 提交时间: 2021-05-08 22:19:31
#include<bits/stdc++.h> using namespace std; #define MAXNUM 222222 #define rep(i,s,t) for(int i=s;i<t;i++) typedef long long ll; ll res[MAXNUM]; struct item { int l, r, id; bool operator <(const item &a)const { return r < a.r; } item(int l,int r,int id): l(l),r(r),id(id) {} }; bool cmp(const item &a, const item&b) { return a.l < b.l; } namespace treea { ll tree[MAXNUM],tree2[MAXNUM]; int tsize; int lowbit(int t) { return t & (-t); } void add(int x, ll y) { for (int i = x; i <= tsize; i += lowbit(i)) tree[i] += y, tree2[i] += x * y; } ll getsum(int x) { ll res = 0,res2=0; for (int i = x; i > 0; i -= lowbit(i)) res += tree[i], res2 += tree2[i]; return res * (x + 1) - res2; } } vector<int> num[MAXNUM]; vector<item> q[MAXNUM],pos,tmp; int main(void) { int n, m, qq,a,b,c; scanf("%d%d%d", &n, &m, &qq); rep(i, 1, n + 1) { scanf("%d", &a); num[a].push_back(i); } rep(i, 1, qq + 1) { scanf("%d%d%d", &a, &b, &c); q[c].emplace_back(a, b, i); } treea::tsize = n; rep(i, 1, m + 1) { tmp.clear(); int before = -1, nowi = -1; rep(i,0,pos.size()) { while (nowi + 1 < i&&pos[nowi + 1].r <= pos[i].l - 1) nowi++; if (nowi != before) tmp.emplace_back(pos[nowi].l, pos[i].r, 1), before = nowi; } for (int k : num[i]) tmp.emplace_back(k, k, -1); sort(tmp.begin(), tmp.end()); int maxnum = 0; for (item &k : tmp) k.l = max(k.l, maxnum), maxnum = max(maxnum, k.l); pos.clear(); pos = tmp,nowi = 0; sort(q[i].begin(), q[i].end()); tmp.push_back({ n + 1,n + 1,-1 }), tmp.insert(tmp.begin(), { 0,0,1 }); for (item &k : q[i]) { while (tmp[nowi + 1].r <= k.r) treea::add(1, tmp[nowi + 1].r-tmp[nowi].r), treea::add(tmp[nowi].l + 1, -(tmp[nowi + 1].r-tmp[nowi].r)),nowi++; res[k.id] += treea::getsum(k.r)-treea::getsum(k.l-1); res[k.id] += max(0, k.r - tmp[nowi].r + 1)* 1LL *max(0, tmp[nowi].l - k.l + 1); } rep(i, 0, nowi) treea::add(1, -(tmp[i + 1].r - tmp[i].r)), treea::add(tmp[i].l + 1, tmp[i + 1].r - tmp[i].r); } rep(i, 1, qq + 1) printf("%lld\n", res[i]); }