18.8.29 考试总结
这道题就是分层图最短路啊啊啊啊啊啊啊 可惜我之前没写过 然后就很zz的没搞出来
dis[ i ][ j ]表示到了第 i 个点经过j个景点的最小距离
就是开一个超级源汇点 然后S向每个小起点连一条长度为排队时间的边 每个终点向T也连排队长度的边
然后就很愉快的SFPA了 最后判断答案就是在T处从大到小枚举景点数 如果发现被更新过就可以输出了 耶
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 5 * 1e3 + 5; int V,m,n,e,l,sink,src,tot,head[N],nex[2 * N],tov[2 * N],val[2 * N]; ll dis[N][N]; bool vis[N][N]; struct sta { int u,num; sta(int u = 0,int num = 0): u(u),num(num) { } }; queue<sta>Q; void add(int u,int v,int w) { tot ++; nex[tot] = head[u]; tov[tot] = v; val[tot] = w; head[u] = tot; } void init( ) { src = 0,sink = V + 1; for(int i = 1;i <= m;i ++) { int pos,pp; scanf("%d%d",& pos,& pp); add(src,pos,pp); } for(int i = 1;i <= n;i ++) { int pos,pp; scanf("%d%d",& pos,& pp); add(pos,sink,pp); } for(int i = 1;i <= e;i ++) { int u,v,w; scanf("%d%d%d",& u,& v,& w); add(u,v,w); } } void SPFA( ) { memset(dis,0x3f3f3f,sizeof(dis)); ll cmp = dis[0][0]; memset(vis,0,sizeof(vis)); vis[src][0] = true; dis[src][0] = 0; Q.push(sta(src,0)); while(! Q.empty( )) { sta a = Q.front( ); Q.pop( ); vis[a.u][a.num] = false; for(int i = head[a.u];i;i = nex[i]) { int v = tov[i]; if(dis[v][a.num + 1] > dis[a.u][a.num] + val[i] && dis[a.u][a.num] + val[i] <= l) { dis[v][a.num + 1] = dis[a.u][a.num] + val[i]; if(! vis[v][a.num + 1]) { vis[v][a.num + 1] = true; Q.push(sta(v,a.num + 1)); } } } } bool tag = true; for(int i = V + 1;i >= 1;i --) if(dis[sink][i] != cmp) { printf("%d",i - 1); tag = false; break; } if(tag) printf("0"); } int main( ) { freopen("park.in","r",stdin); freopen("park.out","w",stdout); scanf("%d%d%d%d%d",& V,& m,& n,& e,& l); init( ); SPFA( ); }
阿这道题是一道数学公式的题
可以预先用滑动窗口处理处每个点$i$向右第一个合法的点 记作$r[i]$ 因为从这以后每个点都必定合法
然后对于某个询问$[L,R]$ 因为所有的$r[i]$都是单调不降的 所以可以二分求出在该区间内最后一个合法的位置
它的答案就是$\sum_{i = L}^{pos}(R - i + r[i] - i)\cdot (R - r[i] + 1) \cdot \frac{1}{2}$
然后化简得
$ (pos - L + 1) * (R \cdot R + R )\cdot \frac{1}{2} + \sum_{i = L}^{pos}(r[i] - r[i] \cdot r[i] + 2i\cdot r[i]+(R +1)\sum_{i = L}^{pos}i$
然后发现前面一坨和后面一坨都是可以直接算的 然后剩下的维护一个关于中间一坨的前缀和就可以了。
代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 5; int n,m,q,a[N],las[N]; ll sum[N],r[N]; void init( ) { for(int i = 1;i <= n;i ++) scanf("%d",& a[i]); int head = 1,tail = 1,tot = 0; for(head = 1;head <= n;head ++) { while(1) { if(tot >= m && tail - head > 1) { r[head] = tail - 1; break; } if(tail > n) { r[head] = N; break; } if(! las[a[tail]] && tail <= n) tot ++; las[a[tail]] = tail; tail ++; } if(las[a[head]] == head) { tot --; las[a[head]] = 0; } } for(int i = 1;i <= n;i ++) { sum[i] = sum[i - 1] + (r[i] - r[i]*r[i] + 2ll*i*r[i]); } } ll find_pos(ll L,ll R) { ll ans = 0; ll rr = R; while(L <= rr) { ll mid = (L + rr) >> 1; if(r[mid] <= R) ans = mid,L = mid + 1; else rr = mid - 1; } return ans; } void solve( ) { while(q --) { ll L,R; scanf("%I64d%I64d",& L,& R); ll pos = find_pos(L,R); if(pos == 0) { printf("0\n"); continue; } ll R1 = (pos - L + 1) * (R * R + R) ; ll R2 = sum[pos] - sum[L - 1]; ll R3 = (R + 1) * (L + pos) * (pos - L + 1) ; printf("%I64d\n",(R1 + R2 - R3)/2); } } int main( ) { freopen("plan.in","r",stdin); freopen("plan.out","w",stdout); scanf("%d%d%d",& n,& m,& q); init( ); solve( ); }
这道题我是讲不清楚了 我下来改题 看代码的时间花费特别多 只能说blutrex大哥代码可读性太差了!!!!
而且还难得一批 最后几个点还T了 人生第一次被卡常数 呕
代码(是被卡常的代码 zc大佬和我写的一样结果他就过了!!! 是因为我这份代码太丑了??)
#include <bits/stdc++.h> using namespace std; typedef long long ull; const int N = 1e3; const ull mod = 2000000011; int n,m; ull q[N],p[N],f[1 << (9 << 1)][65],a3[5]; struct dat { ull a,b; dat(ull a = 0,ull b = 0): a(a),b(b) { } }e[N]; ull fast_pow(ull a,ull b) { ull ans = 1; for(;b;b >>= 1,a = a * a % mod) if(b & 1) ans = ans * a % mod; return ans; } ull inverse(ull a) { return fast_pow(a,mod - 2); } int main( ) { freopen("card.in", "r", stdin); freopen("card.out", "w", stdout); scanf("%d%d",& n,& m); ull s = inverse(1ll * 100 * n); p[n] = 1; a3[0] = 0,a3[1] = inverse(3),a3[2] = 2 * inverse(3) % mod,a3[3] = 1; for(int i = 0;i < n;i ++) scanf("%I64d",& p[i]),p[i] = p[i] * s % mod,p[n] = (p[n] - p[i] + mod) % mod; q[n] = 1; for(int i = 0;i < n;i ++) scanf("%I64d",& q[i]),q[i] = q[i] * s % mod,q[n] = (q[n] - q[i] + mod) % mod; for(int s = (1 << (n << 1)) - 2;s >= 0;s --) { e[m] = dat(1,0); ull v = 0; ull ss = q[n]; for(int i = 0;i < n;i ++) { ss = (ss + q[i] * a3[(s >> (i << 1) & 3)]) % mod; if((s >> (i << 1) & 3) < 3) v = (v + q[i] * a3[((s >> (i << 1) & 3) ^ 3)] % mod * f[s + (1 << (i << 1))][m]) % mod; } e[m - 1] = dat(ss * e[m].a % mod,(ss * e[m].b % mod + v) % mod); for(int j = m - 2;j >= 0;j --) { ull ss = p[n]; v = 0; for(int i = 0;i < n;i ++) { ss = (ss + p[i] * a3[(s >> (i << 1) & 3)]) % mod; if((s >> (i << 1) & 3) < 3) v = (v + p[i] * a3[((s >> (i << 1) & 3) ^ 3)] % mod * f[s + (1 << (i << 1))][j + 1]) % mod; } e[j] = dat(ss * e[j + 1].a % mod,(ss * e[j + 1].b % mod + v) % mod); } f[s][0] = (e[0].a + e[0].b) % mod * inverse(1 - e[0].a + mod) % mod; f[s][m] = (f[s][0] + 1) % mod; for(int k = 1;k < m;k ++) f[s][k] = (e[k].a * f[s][m] + e[k].b ) % mod; } printf("%I64d",f[0][m] % mod); }