NOIP2024加赛8
状态很不好,恼了。虚拟机太卡了,根本交不上去。
flandre
发现选取的肯定是从大到小排序后的一个后缀,然后就做完了,时间复杂度
点此查看代码
#include<bits/stdc++.h> using namespace std; #define rep(i,s,t,p) for(int i = s;i <= t;i += p) #define drep(i,s,t,p) for(int i = s;i >= t;i -= p) #ifdef LOCAL FILE *I = fopen("in.in","r"),*O = fopen("out.out","w"); #else // FILE *I = stdin,*O = stdout; FILE *I = fopen("flandre.in","r"),*O = fopen("flandre.out","w"); #endif using ll = long long;using ull = unsigned long long; using db = double;using ldb = long double; #define int long long const int N = 1e6 + 10; #define pii pair<int,int> #define mk make_pair pii a[N];int n,k; inline void solve(){ cin>>n>>k;rep(i,1,n,1) cin>>a[i].first,a[i].second = i; sort(a+1,a+1+n); int pos = n+1,ans = 0,sum = 0; map<int,int> mp; drep(i,n,1,1){ sum += a[i].first; mp[a[i].first]++; sum += (n-i+1-mp[a[i].first])*k; if(sum > ans){ ans = sum;pos = i; } } cout<<ans<<' '<<n-pos+1<<'\n'; rep(i,pos,n,1) cout<<a[i].second<<' '; } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); solve(); }
meirin
因为有且仅有对
考虑什么时候
假设
将
发现如果
对于区间加,增加的贡献就是
时间复杂度
点此查看代码
#include<bits/stdc++.h> using namespace std; #define rep(i,s,t,p) for(int i = s;i <= t;i += p) #define drep(i,s,t,p) for(int i = s;i >= t;i -= p) using ll = long long;using ull = unsigned long long; using db = double;using ldb = long double; #ifdef LOCAL FILE *I = freopen("in.in","r",stdin),*O = freopen("out.out","w",stdout); #else // FILE *I = stdin,*O = stdout; FILE *I = freopen("meirin.in","r",stdin),*O = freopen("meirin.out","w",stdout); #endif #define int long long const int N = 5e5 + 10,mod = 1e9 + 7; int n,m,a[N],b[N],s1[N],s2[N],p[N],sum[N],ans; signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cin>>n>>m;rep(i,1,n,1) cin>>a[i];rep(i,1,n,1) cin>>b[i]; rep(i,1,n,1) s1[i] = (s1[i-1] + i*a[i]%mod)%mod; drep(i,n,1,1) s2[i] = (s2[i+1] + (n-i+1)*a[i]%mod)%mod; rep(i,1,n,1) p[i] = ((n-i+1)*s1[i-1]%mod + (s2[i])%mod*i%mod)%mod; rep(i,1,n,1) sum[i] = (sum[i-1] + p[i])%mod,ans = (ans + b[i]*p[i]%mod)%mod; rep(test,1,m,1){ int l,r,k;cin>>l>>r>>k; ans = (ans + (sum[r]-sum[l-1]+mod)%mod*k%mod)%mod; cout<<(ans+mod)%mod<<'\n'; } }
sakuya
考虑如果一条边有贡献,那么就是它两端子树内的关键点的乘积乘上
考虑如果对一个点所连的边进行
但是还没完,题目让我们求得是期望,不是贡献,只需要求个平均数就好了,注意要乘一个二。
点此查看代码
#include<bits/stdc++.h> using namespace std; #define rep(i,s,t,p) for(int i = s;i <= t;i += p) #define drep(i,s,t,p) for(int i = s;i >= t;i -= p) #ifdef LOCAL FILE *I = freopen("in.in","r",stdin),*O = freopen("out.out","w",stdout); #else // FILE *I = stdin,*O = stdout; FILE *I = freopen("sakuya.in","r",stdin),*O = freopen("sakuya.out","w",stdout); #endif using ll = long long;using ull = unsigned long long; using db = double;using ldb = long double; #define pii pair<int,int> #define eb emplace_back const int N = 5e5 + 10,mod = 998244353; vector<pii> e[N]; int n,m,f[N],p[N],dep[N],ans = 0; bitset<N> pd; void dfs1(int x,int fa){ if(pd[x]) p[x]++; dep[x] = dep[fa] + 1; for(auto [y,w]:e[x]){ if(y == fa) continue; dfs1(y,x);p[x] += p[y]; } } inline int getval(int x,int y){ if(dep[x] > dep[y]) return 1ll*p[x]*(m-p[x])%mod; else return 1ll*p[y]*(m-p[y])%mod; } void dfs2(int x,int fa){ for(auto [y,w]:e[x]){ f[x] = (f[x] + getval(x,y))%mod; if(y == fa) continue; dfs2(y,x); ans = (ans + 1ll*w*getval(x,y)%mod)%mod; } } inline int power(int a,int b,int mod){ int res = 1; for(;b;b >>= 1,a = 1ll*a*a%mod) if(b&1) res = 1ll*res*a%mod; return res; } signed main(){ cin.tie(nullptr)->sync_with_stdio(false); cin>>n>>m; rep(i,2,n,1){ int x,y,w;cin>>x>>y>>w; e[x].eb(y,w);e[y].eb(x,w); } rep(i,1,m,1){int x;cin>>x;pd.set(x);} dfs1(1,0);dfs2(1,0); int q;cin>>q;int more = power(m,mod-2,mod)*2ll%mod; rep(test,1,q,1){ int x,k;cin>>x>>k; ans = (ans + 1ll*f[x]*k%mod)%mod; cout<<1ll*ans*more%mod<<'\n'; } }
红楼 ~ Eastern Dream
初始化的强化?
根号分治是显然的,对于
但是这样是很不优秀的,修改的复杂度为
考虑差分和分块,具体的,设
对于一次查询,显然有
考虑这个柿子怎么化简到方便维护的形式。
然后后面这个东西就像树状数组区间修改一样维护就行了,具体实现看代码中的qry
函数,时间复杂度
点此查看代码
#include<bits/stdc++.h> using namespace std; #define rep(i,s,t,p) for(int i = s;i <= t;i += p) #define drep(i,s,t,p) for(int i = s;i >= t;i -= p) #ifdef LOCAL FILE *I = freopen("in.in","r",stdin),*O = freopen("out.out","w",stdout); #else // FILE *I = stdin,*O = stdout; FILE *I = freopen("scarlet.in","r",stdin),*O = freopen("scarlet.out","w",stdout); #endif using ll = long long;using ull = unsigned long long; using db = double;using ldb = long double; namespace IO{ #define gc getchar_unlocked #define pc putchar_unlocked template<class T> inline void read(T &x){ x = 0;char s = gc(); for(;s < '0' || '9' < s;s = gc()); for(;'0' <= s && s <= '9';s = gc()) x = (x<<1) + (x<<3) + (s^48); } template<class T,class... Args> inline void read(T &x,Args&... argc){read(x);read(argc...);} template<class T> inline void write(T x){ static int sta[40],top = 0; do sta[++top] = x%10;while(x /= 10); while(top) pc(sta[top--]+'0'); } inline void write(char x){pc(x);} template<class T,class... Args> inline void write(T x,Args... argc){write(x);write(argc...);} #undef gc #undef pc }using IO::read;using IO::write; const int N = 2e5 + 1,M = 450; int n,m,a[N],pos[N],L[M],R[M],siz,len; ll s[M],si[M],pre[M][M],suf[M][M],sum[M][M],num[M],c1[N],c2[N],qz[N]; signed main(){ read(n,m);rep(i,1,n,1) read(a[i]),qz[i] = qz[i-1] + a[i]; len = 450;siz = n/len; rep(i,1,siz,1) L[i] = R[i-1]+1,R[i] = i*len; if(R[siz] < n) siz++,L[siz] = R[siz-1] + 1,R[siz] = n; rep(i,1,siz,1) rep(j,L[i],R[i],1) pos[j] = i; int spl = sqrt(n/5.0); auto qry1 = [&](int l,int r){ if(r == 0) return 0ll; int p = pos[l],q = pos[r];ll res = 0; if(p == q){rep(i,l,r,1) res += c1[i];return res;} rep(i,l,R[p],1) res += c1[i]; rep(i,L[q],r,1) res += c1[i]; rep(i,p+1,q-1,1) res += s[i]; return res; }; auto qry2 = [&](int l,int r){ if(r == 0) return 0ll; int p = pos[l],q = pos[r];ll res = 0; if(p == q){rep(i,l,r,1) res += c2[i];return res;} rep(i,l,R[p],1) res += c2[i]; rep(i,L[q],r,1) res += c2[i]; rep(i,p+1,q-1,1) res += si[i]; return res; }; auto qry = [&](int l,int r){return 1ll*(r-l+1)*qry1(1,l-1)+1ll*(r+1)*(qry1(1,r)-qry1(1,l-1))-qry2(1,r)+qry2(1,l-1);}; int tot = 0; rep(test,1,m,1){ int op,x,y,k = 0; read(op,x,y); if(op == 1){ read(k);y = min(y,x-1); if(x <= spl){ rep(i,0,y,1) sum[x][i] += k; num[x] += 1ll*k*(y+1); pre[x][0] = sum[x][0]; rep(i,1,x-1,1) pre[x][i] = pre[x][i-1] + sum[x][i]; drep(i,x-1,0,1) suf[x][i] = suf[x][i+1] + sum[x][i]; } else{ y++; rep(i,1,n,x){ int p = pos[i],iy = i+y; ll ik = 1ll*i*k; s[p] += k,si[p] += ik,c1[i] += k,c2[i] += ik; if(iy <= n) s[pos[iy]] -= k,si[pos[iy]] -= 1ll*iy*k,c1[iy] -= k ,c2[iy] -= 1ll*iy*k; } } } else{ ll ans = 0; rep(now,1,spl,1){ if(y-x < now) rep(i,x,y,1) ans += sum[now][(i-1)%now]; else{ x--,y--; ans += suf[now][x%now];ans += pre[now][y%now]; x++,y++; ans += ((y-((y-1)%now)-1)-(x+(now-(x-1)%now))+1)/now*num[now]; } } write(qry(x,y)+ans+qz[y]-qz[x-1],'\n'); } } }
p
__________________________________________________________________________________________
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18572926
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】