题解 整数序列
《关于我先猜是根号分治然后发现时限是 7s 于是联想到这可能是 SDOI2022 Day1T1 这个事》
首先有一个 的处理两种颜色的做法,可以处理 大-大,小-小
然后 大-小 怎么办呢?
令块长为 ,那么对较小的颜色枚举区间是 的,再对每个区间枚举可行的较大颜色区间是 的
猜测跑不满,于是将块长调成 可以通过
赛后发现 均可以通过
然后正解是怎么处理 大-小 的呢?
每有一个小的颜色,就向两边扩展一个大的颜色
只有被扩展到的大的颜色是有用的(因为最后要求两种颜色出现的次数一样)
这样复杂度严格
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 300010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#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 int read() {
int 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;
ll a[N], b[N];
namespace force{
int top;
ll tem[N<<1], *pre=tem+N;
vector<int> pos[N];
pair<int, ll> sta[N];
map<pair<int, int>, ll> mp;
void solve() {
for (int i=1; i<=n; ++i) pos[a[i]].pb(i);
for (int i=1,x,y; i<=q; ++i) {
// cout<<"i: "<<i<<endl;
x=read(); y=read();
if (!pos[x].size()||!pos[y].size()) {cout<<"-1"<<endl; continue;}
if (mp.find({x, y})!=mp.end()) {printf("%lld\n", mp[{x, y}]); continue;}
int p1=0, p2=0; top=0;
while (p1<pos[x].size()||p2<pos[y].size()) {
int minn=n+1;
if (p1<pos[x].size()) minn=min(minn, pos[x][p1]);
if (p2<pos[y].size()) minn=min(minn, pos[y][p2]);
if (p1<pos[x].size()&&minn==pos[x][p1]) sta[++top]={1, b[pos[x][p1++]]};
if (p2<pos[y].size()&&minn==pos[y][p2]) sta[++top]={-1, b[pos[y][p2++]]};
}
int cnt=0, l, r;
ll sum=0, ans=-INF;
pre[l=r=0]=0;
for (int j=1; j<=top; ++j) {
cnt+=sta[j].fir; sum+=sta[j].sec;
while (l>cnt) pre[--l]=INF;
while (r<cnt) pre[++r]=INF;
ans=max(ans, sum-pre[cnt]);
pre[cnt]=min(pre[cnt], sum);
}
printf("%lld\n", mp[{x, y}]=ans);
}
}
}
namespace task1{
int cnt[N], lst[N], nxt[N], top, sqr;
pair<int, ll> sta[N];
vector<int> pos[N];
vector<pair<int, int>> que[N];
map<pair<int, int>, ll> mp;
ll tem[N<<1], *pre=tem+N, ans[1000010], sum[N];
inline int qcnt(int l, int r) {return cnt[r]-cnt[max(l-1, 0)];}
inline ll qsum(int l, int r) {return sum[r]-sum[max(l-1, 0)];}
ll solve1(int x, int y) {
if (x>y) swap(x, y);
if (mp.find({x, y})!=mp.end()) return mp[{x, y}];
int p1=0, p2=0; top=0;
while (p1<pos[x].size()||p2<pos[y].size()) {
int minn=n+1;
if (p1<pos[x].size()) minn=min(minn, pos[x][p1]);
if (p2<pos[y].size()) minn=min(minn, pos[y][p2]);
if (p1<pos[x].size()&&minn==pos[x][p1]) sta[++top]={1, b[pos[x][p1++]]};
if (p2<pos[y].size()&&minn==pos[y][p2]) sta[++top]={-1, b[pos[y][p2++]]};
}
int cnt=0, l, r;
ll sum=0, ans=-INF;
pre[l=r=0]=0;
for (int j=1; j<=top; ++j) {
cnt+=sta[j].fir; sum+=sta[j].sec;
while (l>cnt) pre[--l]=INF;
while (r<cnt) pre[++r]=INF;
ans=max(ans, sum-pre[cnt]);
pre[cnt]=min(pre[cnt], sum);
}
return mp[{x, y}]=ans;
}
void solve() {
sqr=pow(n, 0.3);
// cout<<"sqr: "<<sqr<<endl;
for (int i=1; i<=n; ++i) pos[a[i]].pb(i);
for (int i=1,x,y; i<=q; ++i) {
x=read(); y=read();
if (!pos[x].size()||!pos[y].size()) {ans[i]=-1; continue;}
if (pos[x].size()>pos[y].size()) swap(x, y);
int sizx=pos[x].size(), sizy=pos[y].size();
if (sizx<=sqr&&sizy<=sqr) ans[i]=solve1(x, y);
else if (sizx>sqr&&sizy>sqr) ans[i]=solve1(x, y);
else que[y].pb({x, i});
}
for (int i=1; i<=n; ++i) if (pos[i].size()&&pos[i].size()>sqr) {
// cout<<"i: "<<i<<endl;
for (int j=1; j<=n+1; ++j) cnt[j]=cnt[j-1]+(a[j]==i);
for (int j=1; j<=n+1; ++j) sum[j]=sum[j-1]+(a[j]==i)*b[j];
for (int j=1,t=0; j<=n+1; ++j) lst[j]=t, t=a[j]==i?j:t;
for (int j=n,t=n+1; j; --j) nxt[j]=t, t=a[j]==i?j:t;
for (auto it:que[i]) {
// cout<<"it: "<<it.fir<<endl;
if (mp.find({min(it.fir, i), max(it.fir, i)})!=mp.end()) {ans[it.sec]=mp[{min(it.fir, i), max(it.fir, i)}]; continue;}
ll val=-INF;
// cout<<"pos_x: "; for (auto it:pos[i]) cout<<it<<' '; cout<<endl;
// cout<<"pos_y: "; for (auto t:pos[it.fir]) cout<<t<<' '; cout<<endl;
for (int p1=0; p1<pos[it.fir].size(); ++p1) {
ll pre=0;
for (int p2=p1; p2<pos[it.fir].size(); ++p2) {
int need=p2-p1+1;
// cout<<"need: "<<need<<endl;
int real=qcnt(pos[it.fir][p1], pos[it.fir][p2]);
pre+=b[pos[it.fir][p2]];
if (real>need) continue;
else if (real==need) val=max(val, pre+qsum(pos[it.fir][p1], pos[it.fir][p2]));
else {
int l=pos[it.fir][p1], r=pos[it.fir][p2];
// int dlt=min(need-real, min(cnt[l], qcnt(r, n)));
int t1=l, t2=r;
// cout<<"lr: "<<t1<<' '<<t2<<endl;
int liml=0, limr=n+1;
if (p2+1<pos[it.fir].size()) limr=min(limr, pos[it.fir][p2+1]);
if (p1) liml=max(liml, pos[it.fir][p1-1]);
// cout<<"lim: "<<liml<<' '<<limr<<endl;
while (t2<limr&&qcnt(t1, t2)<need) t2=nxt[t2];
// cout<<lst[t1]<<' '<<lst[t2]<<endl;
if (t2>=limr) t2=max(lst[t2], r);
// cout<<"need&now: "<<need<<' '<<qcnt(t1, t2)<<endl;
while (t1>liml&&qcnt(t1, t2)<=need) {
// cout<<"try: "<<t1<<' '<<t2<<' '<<qcnt(t1, t2)<<endl;
assert(t2<limr);
if (t1>liml&&t2<limr&&qcnt(t1, t2)==need) val=max(val, pre+qsum(t1, t2)); //, cout<<"t: "<<t1<<' '<<t2<<endl;
if (qcnt(t1, t2)==need) t2=max(lst[t2], r);
t1=lst[t1]; //t2=max(lst[t2], r);
}
}
ans[it.sec]=mp[{min(it.fir, i), max(it.fir, i)}]=val;
}
}
}
}
for (int i=1; i<=q; ++i) printf("%lld\n", ans[i]);
}
}
signed main()
{
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
n=read(); q=read();
bool flag=1;
for (int i=1; i<=n; ++i) a[i]=read();
for (int i=1; i<=n; ++i) if ((b[i]=read())<0) flag=0;
// force::solve();
// if (n<=5000) force::solve();
// else task1::solve();
task1::solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构