洛谷 P5012 水の数列

Problem

给你一个长度为\(n(n\le10^6)\)的数列,有\(T(T\le 10^3)\)组询问,每一组询问查询区间\([l,r]\),请选择一个\(x\),将所有\(\le x\)的数标记后得到的段数\(\in[l,r]\),得分为每一段连续标记的区间的长度的平方和除以\(x\),最大化得分。

\(0\le a_i\le 10^6\).

强制在线。

Solution

注意到没有修改,那么就可以愉快的预处理。

首先从小到大枚举\(x(1\le x\le 10^6)\)同时用并查集维护连通性,计算答案为\(x\)时有多少段,得分是多少。

把这个\((得分,x)\)二元组放到一个数组中(下标为段数),用线段树维护即可。

结果大概可能是像我一样辛辛苦苦打完线段树,发现线段树无论如何都会\(MLE\)……线段树的空间复杂度是\(4\times n\)左右,而分块的空间复杂度只有\(n+\sqrt{n}\),于是换成分块就可以愉快的AC啦!这是一种时间换空间的方法。

Code

代码实属远古且肉麻,见谅。

/**************************************************************
* Problem: 5012
* Author: Vanilla_chan
* Date: 20210331
* E-Mail: Vanilla_chan@outlook.com
**************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
#ifdef ONLINE_JUDGE
char buf[1<<23],* p1=buf,* p2=buf,obuf[1<<23],* O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
using namespace std; namespace oi
{
inline bool isdigit(const char& ch)
{
return ch<='9'&&ch>='0';
}
inline bool isalnum(const char& ch)
{
return (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9');
}
struct istream
{
char ch;
bool fu;
template<class T>inline istream& operator>>(T& d)
{
fu=d=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=1,ch=getchar();
d=ch-'0';ch=getchar();
while(isdigit(ch))
d=(d<<3)+(d<<1)+(ch^'0'),ch=getchar();
if(fu) d=-d;
return *this;
}
inline istream& operator>>(char& ch)
{
ch=getchar();
for(;!isalnum(ch);ch=getchar());
return *this;
}
inline istream& operator>>(string& str)
{
str.clear();
for(;!isalnum(ch);ch=getchar());
while(isalnum(ch))
str+=ch,ch=getchar();
return *this;
}
}cin;
inline int read()
{
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)) { x=x*10+ch-'0';ch=getchar(); }
return x*fu;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do { G[++g]=x%10;x/=10; } while(x);
for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
};
using namespace oi;
#define N 1000010 int n,m;
int maxnum;
int a[N],f[N];
LL sze[N];
int getf(int x)
{
if(f[x]==x) return x;
return f[x]=getf(f[x]);
}
LL now;
int duan;
void merge(int x,int y)
{
x=getf(x);
y=getf(y);
if(x==y) return;
duan--;
now-=sze[x]*sze[x];
now-=sze[y]*sze[y];
f[y]=x;
sze[x]+=sze[y];
sze[y]=0;
now+=sze[x]*sze[x];
}
vector<int>pos[N];
struct node
{
LL ans;
LL x;
node(LL defen=0,int xx=0)
{
ans=defen;
x=xx;
}
IL bool operator>(const node &z)const
{
if(ans==0) return 0;
if(z.ans==0) return 1;
if(ans*z.x==z.ans*x) return x>z.x;
return ans*z.x>z.ans*x;
}
};
IL node max(const node &x,const node &y)
{
return x>y?x:y;
}
/*
namespace Tree
{
::node a[N];
struct node
{
::node mx;
#define mx(x) b[x].mx
}b[N<<2];
void upd(int p)
{
mx(p)=::max(mx(p<<1),mx(p<<1|1));
}
void build(int p,int l,int r)
{
if(l==r)
{
mx(p)=a[l];
return;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
upd(p);
}
::node ask(int p,int L,int R,int l,int r)
{
if(l<=L&&R<=r)
{
return mx(p);
}
int mid=L+R>>1;
if(l<=mid&&r>mid) return max(ask(p<<1,L,mid,l,r),ask(p<<1|1,mid+1,R,l,r));
if(l<=mid) return ask(p<<1,L,mid,l,r);
else return ask(p<<1|1,mid+1,R,l,r);
}
};
*/
namespace Block
{
::node a[N],mx[2010];
int L[2010],R[2010],belong[N];
int s,block;
void build()
{
s=sqrt(n);
block=n/s;
for(int i=1;i<=s;i++)
{
L[i]=block*(i-1)+1;
R[i]=block*i;
}
R[s]=n;
for(int i=1;i<=s;i++)
{
for(int j=L[i];j<=R[i];j++)
{
belong[j]=i;
mx[i]=max(mx[i],a[j]);
}
}
}
::node ask(int l,int r)
{
::node ans;
if(belong[r]-belong[l]<=3)
{
for(int i=l;i<=r;i++) ans=::max(ans,a[i]);
}
else
{
for(int i=belong[l]+1;i<=belong[r]-1;i++) ans=::max(ans,mx[i]);
for(int i=l;i<=R[belong[l]];i++) ans=::max(ans,a[i]);
for(int i=L[belong[r]];i<=r;i++) ans=::max(ans,a[i]);
}
return ans;
}
}
void pre()
{
for(int i=1;i<=n;i++)
{
f[i]=0;
sze[i]=0;
}
for(int i=1;i<=n;i++) pos[a[i]].push_back(i);
for(int i=1;i<=maxnum;i++)
{
for(unsigned int j=0;j<pos[i].size();j++)
{
f[pos[i][j]]=pos[i][j];
sze[pos[i][j]]=1;
now++;
duan++;
if(f[pos[i][j]-1]) merge(pos[i][j],pos[i][j]-1);
if(f[pos[i][j]+1]) merge(pos[i][j],pos[i][j]+1);
}
// cout<<"x="<<i<<" "<<"duan="<<duan<<" pts="<<now<<endl;
Block::a[duan]=max(Block::a[duan],node(now,i));
}
}
LL lastans;
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n=read();
m=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
maxnum=max(maxnum,a[i]);
}
pre();
// Tree::build(1,1,n);
Block::build();
node ans;
LL l,r,a,b,x,y;
for(int i=1;i<=m;i++)
{
a=read()%n+n;
b=read()%n+n;
x=read()%n+n;
y=read()%n+n;
l=(a*lastans%n+x-1)%n+1;
r=(b*lastans%n+y-1)%n+1;
if(l>r) swap(l,r);
ans=Block::ask(l,r);
if(ans.ans)
{
cout<<ans.ans<<" "<<ans.x<<endl;
cout<<l<<" "<<r<<" "<<lastans<<endl;
lastans=ans.x*ans.ans%n;
}
else
{
cout<<"-1 -1"<<endl;
cout<<l<<" "<<r<<" "<<lastans<<endl;
lastans=1%n;
} }
return 0;
}

Other

如果您最后一排\(RE\)/全\(WA\),除了在计算数组大小,检查算法的正确性,别忘记看看加密方式QAQ

还有,记得多%

时隔几个月,在大家的帮助下(见讨论区)终于完成了历史性的突破,\(95pts\to AC\),通过了这道题。

无可奈何花落去,似曾相识燕归来。小园香径独徘徊。

洛谷 P5012 水の数列的更多相关文章

  1. P5012 水の数列

    P5012 水の数列 离线处理出选择每个数得到区间数得到刚开始的得分 \(RMQ_{ij}\)表示\(i\)~\(i\)+\(2^j\)-1的区间最大值 #include<cstdio> ...

  2. [洛谷P3228] [HNOI2013]数列

    洛谷题目链接:[HNOI2013]数列 题目描述 小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨.股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N.在疯涨的K天中小T观察到: ...

  3. P5198 [USACO19JAN]Icy Perimeter S (洛谷) (水搜索)

    同样是因为洛谷作业不会写…… 写(水)博客啦. 直接放题目吧,感觉放在代码框里好看点 Farmer John要开始他的冰激凌生意了!他制造了一台可以生产冰激凌球的机器,然而不幸的是形状不太规则,所以他 ...

  4. 【洛谷 P1667】 数列 (贪心)

    题目链接 对于一个区间\([x,y]\),设这个区间的总和为\(S\) 那么我们在前缀和(设为\(sum[i]\))的意义上考虑到原操作其实就是\(sum[x−1]+=S\) , \(sum[x]+S ...

  5. 洛谷P1415 拆分数列[序列DP 状态 打印]

    题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输出使得最后一个数最小的同时 ...

  6. 洛谷P1415 拆分数列(dp)

    题目链接:传送门 题目: 题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输 ...

  7. 洛谷P1415 拆分数列

    题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输出使得最后一个数最小的同时 ...

  8. 洛谷 P1415 拆分数列 解题报告

    拆分数列 题目背景 [为了响应党中央勤节俭.反铺张的精神,题目背景描述故事部分略去^-^] 题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数. 如果有多组解,则输出使得最后一个 ...

  9. 洛谷 P2609 [ZJOI2012]数列 解题报告

    P2609 [ZJOI2012]数列 题目描述 小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式: A(0)=0 A(1)=1 A(2i)=A(i) (对于任意 i>0 ...

  10. 洛谷 P2401 不等数列 题解

    每日一题 day25 打卡 Analysis dp[i][j]=dp[i-1][j-1]*(i-j)+dp[i-1][j]*(j+1); 其中i和j是表示前i个数中有j个小于号,j<=i-1 要 ...

随机推荐

  1. nnUNet 使用方法

    首先明确分割任务. 其次明确研究方法和步骤. 再做好前期准备,如数据集的采集.标注以及其中的训练集/测试集划分. 其中的参考链接: (四:2020.07.28)nnUNet最舒服的训练教程(让我的奶奶 ...

  2. mac 触控板 三指拖动

    1. 打开系统偏好设置 点击屏幕左上角的苹果图标(),选择"系统设置". 2. 打开指针控制 在系统偏好设置窗口左侧栏中,点击"辅助功能",然后在右侧列表中, ...

  3. UNIX 系统

    UNIX 系统的历史,UNIX 是操作系统的开山鼻祖,是操作系统的发源地,后来的 Windows 和 Linux 都参考了 UNIX. 有人说,这个世界上只有两种操作系统: UNIX 和类 UNIX ...

  4. Shell语言编程(炼气)

    1. Shell脚本执行方式 执行方式 应用及场景 通过sh或bash 书写脚本后,最常用的方式,在其他非红帽系统中,建议使用bash运行脚本 通过.点或source 加载/生效配置文件(环境变量,别 ...

  5. 【JVM之内存与垃圾回收篇】垃圾回收相关算法

    垃圾回收相关算法 标记阶段:引用计数算法 在堆里存放着几乎所有的 Java 对象实例,在 GC 执行垃圾回收之前,首先需要区分出内存中哪些是存活对象,哪些是已经死亡的对象.只有被标记为己经死亡的对象, ...

  6. QwQ-32B:用强化学习打造的AI推理黑科技 🚀

    现在就体验 QwQ-32B:https://qwq32.com AI界的新星闪耀登场 小伙伴们,AI领域又出现重大突破啦!Qwen团队最新发布的QwQ-32B模型简直太厉害了!这个只有320亿参数的模 ...

  7. 2020年devops的7个发展趋势

    2020年devops的7个发展趋势 2019年对DevOps从业者来说是激动人心的一年,DevOps继续快速增长.大多数组织都在执行或评估他们的DevOps策略.那么,到2020年,DevOps.基 ...

  8. Python读取CSV文件并存储到MySQL

    在项目中对后台进行测试时,经常会遇到要在数据库新增数据,那么如何快速新增数据来提高工作效率呢? 现整理如下: 代码内容(csv_to_mysql.py): # coding=utf-8import p ...

  9. v-bind,v-if,v-for,v-on,v-model基本用法

    总结: 1.v-bind绑定数据:标签属性v-bind:title='xxx',简写:title='xxx', 标签内容{{xxx}} <span :title='message'>{{m ...

  10. 前端速成之路——html、css

    项目一知识点 单表视图列表 标题标签 <h1>用户注册</h1> 分割线与换行 <hr> <br> 表单提交 get:通过浏览器地址栏传递值 post: ...