题目

点这里

考场思考

大概是标准的莫队吧,离散之后来一个线段树加莫队就可以了。

时间复杂度 \(\mathcal O(n\sqrt n\log n)\) 。

然而被卡常了...只有 \(40pts\) ...

自闭中...

#pragma GCC optimize(2)
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std; #define rep(i,__l,__r) for(signed i=__l,i##_end_=__r;i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=__l,i##_end_=__r;i>=i##_end_;--i)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
#define LL long long
#define ull unsigned long long
#define uint unsigned int
#define pii pair<int,int>
#define Endl putchar('\n')
// #define FILEOI
#define int long long
// #define int unsigned
#define lc (i<<1)
#define rc (i<<1|1) #ifdef FILEOI
# define MAXBUFFERSIZE 500000
inline char fgetc(){
static char buf[MAXBUFFERSIZE+5],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXBUFFERSIZE,stdin),p1==p2)?EOF:*p1++;
}
# undef MAXBUFFERSIZE
# define cg (c=fgetc())
#else
# define cg (c=getchar())
#endif
template<class T>inline void qread(T& x){
char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
if(f)x=-x;
}
inline int qread(){
int x=0;char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
return f?-x:x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
template<class T>void fwrit(const T x){
if(x<0)return (void)(putchar('-'),fwrit(-x));
if(x>9)fwrit(x/10);putchar(x%10^48);
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
} const int MAXN=1e5; int a[MAXN+5],sqrtN,ans[MAXN+5];
int has[MAXN+5]; struct query{
int id,l,r;
query(const int I=0,const int L=0,const int R=0):id(I),l(L),r(R){}
bool operator < (const query a)const{
if((l/sqrtN)^(a.l/sqrtN))return (l/sqrtN)<(a.l/sqrtN);
return r<a.r;
}
}q[MAXN+5];
struct node{
int l,r,mid,maxx;
node(const int L=0,const int R=0):l(L),r(R),mid((L+R)>>1),maxx(0){}
}tre[MAXN<<2|2];
inline void buildtre(const int i,const int l,const int r){
tre[i]=node(l,r);
if(l==r)return;
int mid=(l+r)>>1;
buildtre(lc,l,mid);
buildtre(rc,mid+1,r);
}
inline void pushup(const int i){
tre[i].maxx=Max(tre[lc].maxx,tre[rc].maxx);
return;
}
inline void add(const int i,const int p,const int delta){
if(tre[i].l==tre[i].r){
tre[i].maxx+=has[tre[i].l]*delta;
return;
}
if(p<=tre[i].mid)add(lc,p,delta);
else add(rc,p,delta);
pushup(i);
}
inline void delet(const int i,const int p,const int delta){
if(tre[i].l==tre[i].r){
tre[i].maxx-=has[tre[i].l]*delta;
return;
}
if(p<=tre[i].mid)delet(lc,p,delta);
else delet(rc,p,delta);
pushup(i);
} int N,Q,X[MAXN+5],tmp[MAXN+5]; signed main(){
#ifdef FILEOI
freopen("file.in","r",stdin);
freopen("file.out","w",stdout);
#endif
qread(N,Q);
sqrtN=(int)sqrt(N*1.0); rep(i,1,N)tmp[i]=X[i]=qread();
sort(tmp+1,tmp+N+1);
int tN=unique(tmp+1,tmp+N+1)-tmp-1;
int pos;
rep(i,1,N){
pos=lower_bound(tmp+1,tmp+tN+1,X[i])-tmp;
has[pos]=X[i];
X[i]=pos;
} int x,y;
rep(i,1,Q){
qread(x,y);
q[i]=query(i,x,y);
}
sort(q+1,q+Q+1); buildtre(1,1,tN);
int l=1,r=0;
rep(t,1,Q){
while(r<q[t].r)add(1,X[++r],1);
while(r>q[t].r)delet(1,X[r--],1);
while(l<q[t].l)delet(1,X[l++],1);
while(l>q[t].l)add(1,X[--l],1);
ans[q[t].id]=tre[1].maxx;
}
rep(i,1,Q)writc(ans[i],'\n');
return 0;
}

思路分析及标程

其实正解就是莫队,但是加入了一些小优化。

首先思考:如果没有回退操作怎么办?

那很简单,可以不用线段树维护了,这样我们就可以丢掉 \(\log\) 了。

但是怎么才能实现呢?

分析:我们的回退操作是在哪里涉及到的?

其实,对于一般莫队,在左端点都在同一个块里面的时候,我们的右端点都是递增的,这是无疑的。

但是我们的左端点却在进行较小范围的摆动,这让我们十分不爽,并只得加入线段树来进行优化。

如果询问的两个端点在同一个块中,直接暴力计算,时间复杂度 \(\mathcal O(\sqrt N)\) 。

如果不在同一个块中,这时候右端点是不断递增的,因此暴力计算右端点的复杂度为 \(\mathcal O(N)\) 。

但是左端点的位置在块内可是飘忽不定的啊,

简单,每次询问之后把左端点移动到所在块的最右段即可,每次计算左端点的复杂度为 \(\mathcal O(\sqrt N)\) 。

因为有 \(\mathcal O(\sqrt N)\) 个块,因此总的时间复杂度为 \(\mathcal O(N\sqrt N)\) 。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; #define rep(i,__l,__r) for(signed i=__l,i##_end_=__r;i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=__l,i##_end_=__r;i>=i##_end_;--i)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
#define LL long long
#define ull unsigned long long
#define uint unsigned int
#define pii pair<int,int>
#define Endl putchar('\n')
// #define FILEOI
#define int long long
// #define int unsigned
// #define lc (i<<1)
// #define rc (i<<1|1) #ifdef FILEOI
# define MAXBUFFERSIZE 500000
inline char fgetc(){
static char buf[MAXBUFFERSIZE+5],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXBUFFERSIZE,stdin),p1==p2)?EOF:*p1++;
}
# undef MAXBUFFERSIZE
# define cg (c=fgetc())
#else
# define cg (c=getchar())
#endif
template<class T>inline void qread(T& x){
char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
if(f)x=-x;
}
inline int qread(){
int x=0;char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
return f?-x:x;
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
template<class T>void fwrit(const T x){
if(x<0)return (void)(putchar('-'),fwrit(-x));
if(x>9)fwrit(x/10);putchar(x%10^48);
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
} const int MAXN=1e5; int ans[MAXN+5],maxx,alblock;
int N,Q,X[MAXN+5],has[MAXN+5],tN,block[MAXN+5],sqN,cnt[MAXN+5]; struct Query{
int l,r,id;
inline Query(const int L=0,const int R=0,const int I=0):l(L),r(R),id(I){}
inline bool operator <(const Query rhs)const{
if(block[l]==block[rhs.l])return r<rhs.r;
return block[l]<block[rhs.l];
}
}q[MAXN+5]; inline void init(){
qread(N,Q);sqN=(int)sqrt(N*1.0);
rep(i,1,N){
X[i]=has[i]=qread();
block[i]=(i+sqN-1)/sqN;
alblock=Max(alblock,block[i]);
}
sort(has+1,has+N+1);
tN=unique(has+1,has+N+1)-has-1;
rep(i,1,N)X[i]=lower_bound(has+1,has+tN+1,X[i])-has;
} inline void getQuery(){
int l,r;
rep(i,1,Q){
qread(l,r);
q[i]=Query(l,r,i);
}
sort(q+1,q+Q+1);
} inline int solve(const int l,const int r){
static int tmp[MAXN+5];int tmax=0;
rep(i,l,r)tmp[X[i]]=0;
rep(i,l,r)++tmp[X[i]],tmax=Max(tmax,tmp[X[i]]*has[X[i]]);
return tmax;
} inline void add(const int i){
++cnt[X[i]];
maxx=Max(cnt[X[i]]*has[X[i]],maxx);
} inline void delet(const int i){
--cnt[X[i]];
} inline int Get(int i,const int bid){
int Br=bid*sqN,l=Br+1,r=l-1,cur;maxx=0;
memset(cnt,0,sizeof cnt);
for(;block[q[i].l]==bid;++i){
if(block[q[i].l]==block[q[i].r]){
ans[q[i].id]=solve(q[i].l,q[i].r);
continue;
}
while(r<q[i].r)add(++r);
cur=maxx;
while(l>q[i].l)add(--l);
ans[q[i].id]=maxx;
while(l<Br+1)delet(l++);
maxx=cur;
}
return i;
} signed main(){
#ifdef FILEOI
freopen("file.in","r",stdin);
freopen("file.out","w",stdout);
#endif
init();
getQuery(); for(int i=1,id=1;id<=alblock;++id)
i=Get(i,id); rep(i,1,Q)writc(ans[i],'\n');
return 0;
}

「题解」「JOISC 2014 Day1」历史研究的更多相关文章

  1. 「JOISC 2014 Day1」巴士走读

    「JOISC 2014 Day1」巴士走读 将询问离线下来. 从终点出发到起点. 由于在每个点(除了终点)的时间被过来的边固定,因此如果一个点不被新的边更新,是不会发生变化的. 因此可以按照时间顺序, ...

  2. 「JOISC 2014 Day1」 历史研究

    「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...

  3. 「JOISC 2014 Day1」历史研究 --- 回滚莫队

    题目又臭又长,但其实题意很简单. 给出一个长度为\(N\)的序列与\(Q\)个询问,每个询问都对应原序列中的一个区间.对于每个查询的区间,设数\(X_{i}\)在此区间出现的次数为\(Sum_{X_{ ...

  4. 【LOJ】#3032. 「JOISC 2019 Day1」馕

    LOJ#3032. 「JOISC 2019 Day1」馕 处理出每个人把馕切成N段,每一段快乐度相同,我们选择第一个排在最前的人分给他的第一段,然后再在未选取的的人中选一个第二个排在最前的切一下,并把 ...

  5. 【LOJ】#3031. 「JOISC 2019 Day1」聚会

    LOJ#3031. 「JOISC 2019 Day1」聚会 听说随机可过? 我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链 ...

  6. 【LOJ】#3030. 「JOISC 2019 Day1」考试

    LOJ#3030. 「JOISC 2019 Day1」考试 看起来求一个奇怪图形(两条和坐标轴平行的线被切掉了一个角)内包括的点个数 too naive! 首先熟练的转化求不被这个图形包含的个数 -- ...

  7. 「JOISC 2022 Day1」京都观光 题解

    Solution 考虑从\((x_1,y_1)\)走到\((x_2,y_2)\)满足只改变一次方向,则容易求出先向南走当且仅当 \[\frac{a_{x_1} - a_{x_2}}{x_1 - x_2 ...

  8. LOJ#2882. 「JOISC 2014 Day4」两个人的星座(计算几何)

    题面 传送门 题解 我们发现如果两个三角形相离,那么这两个三角形一定存在两条公切线 那么我们可以\(O(n^2)\)枚举其中一条公切线,然后可以暴力\(O(n^3)\)计算 怎么优化呢?我们可以枚举一 ...

  9. bzoj4244 & loj2878. 「JOISC 2014 Day2」邮戳拉力赛 括号序列+背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4244 https://loj.ac/problem/2878 题解 挺妙的一道题. 一开始一直 ...

随机推荐

  1. python之路之html

    def index(request): print request.POST print request.GET print request.FILES for item in request.FIL ...

  2. Go_sql注入

    我们任何时候都不应该自己拼接SQL语句! sqlInjectDemo("xxx' or 1=1#") sqlInjectDemo("xxx' union select * ...

  3. leetcode 72.编辑距离(dp)

    链接:https://leetcode-cn.com/problems/edit-distance/submissions/ 设dp[i][j]表示串s1前i个字符变换成串s2前j个字符所需要的最小操 ...

  4. ThinkPhp5 中Volist标签的用法

    Volist标签一般是和内置方法assign()搭配使用,将值从后台传到前台,是当下比较流行的一种传值方法 本文实例讲述了ThinkPHP模板循环输出Volist标签用法.分享给大家供大家参考,具体如 ...

  5. 结合webpack使用vue-router和它的子路由,即路由嵌套

    在上一个项目的基础上进行的,所以基本的配置在这里就不赘述了. 一.结合webpack使用vue-router 1.新建组件.vue文件 2.启用路由 安装插件cnpm i vue-router -S ...

  6. JavaWeb01-动态网页

    01.动态网页的优势 动态网页是在服务器端运行的程序!随不同用户,不同条件 返回不同的结果! 001.交互性:网页会根据用户的要求和选择而动态的改变和现实网页内容! 002.自动更新:无需改变页面的代 ...

  7. Linux - 命令 - 查找命令总结

    关于查找文件的几个命令 一.find命令 find是最常用也是最强大的查找命令,可以查找任何类型的文件 find命令的一般格式: find <指定目录><指定条件><指定 ...

  8. Linux netstat命令详解(检验本机各端口的网络连接情况)

    netstat命令用于显示与IP.TCP.UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况.netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP ...

  9. 树莓派4B踩坑指南 - (11)免费搭建网站(宝塔,花生壳)

    目录 宝塔 安装宝塔面板 登录及初始化设置 安装网站 花生壳 安装花生壳 设置花生壳 测试 问题(未解决但不影响使用) 网站统计 树莓派这么低的功耗,不用来当服务器总感觉有点浪费...完成效果:htt ...

  10. docker中安装mysql遇到的问题

    在虚拟机上用docker安装了一个mysql最新版,然后在本地用sqlyog区连接报错‘plugin  cachin_sha2_password  could  not  be  loaded’经过上 ...