题目

点这里

考场思考

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

时间复杂度 \(\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. 第五十三篇 Linux相关——Web服务器

        No.1. Apache基本操作 安装:sudo yum -y install httpd 启动:service httpd start 停止:service httpd stop 查看服务运 ...

  2. 题解【UVA10054】The Necklace

    题目描述 输入格式 输出格式 题意简述 有一种由彩色珠子连接而成的项链.每个珠子的两半由不同颜色组成.如图所示,相邻两个珠子在接触的地方颜色相同.现在有一些零碎的珠子,需要确认它们是否可以复原成完整的 ...

  3. Java通过反射读取泛型

    1.在这里有必要先提一句关于javabean,建议有一个构造器,而不是必须要写的,这是一个良好的习惯. 这样做肯定是有好处的,如果你的一个类写了带参的构造方法,而没有写空的构造方法,那么,如有有一个类 ...

  4. 问题总结:mysql和javaweb工程连接的过程中容易产生的问题

    问题背景:自己在本机的mysql8瘫痪了,将Oracle中的数据迁移到mysql之后,配置好javaweb工程和虚拟机上的远程Mysql连接的文件之后:遇见了无法访问的问题 具体的配置: dataso ...

  5. C# 泛型说明

    详细说明转 https://www.cnblogs.com/dotnet261010/p/9034594.html 最近项目用到了多个参数的泛型方法,这里说明下泛型的组成: /// <summa ...

  6. ubuuntu截图

    方法1: 按 print screen sysrq 方法2: 系统设置 选择键盘 选择快捷键窗口 选择截图 按照自己的习惯更改快捷键即可.

  7. Loading class `com.mysql.jdbc.Driver'. This is deprecated

    注意mysql的版本,pom.xml里面的版本.External Librarlies里面的mysql版本.application.properties版本都要检查 有时候还会报 Invalid bo ...

  8. AcWing 869. 试除法求约数

    #include <iostream> #include <algorithm> #include <vector> using namespace std; ve ...

  9. AcWing 861. 二分图的最大匹配 匈牙利算法

    #include <cstring> #include <iostream> #include <algorithm> using namespace std; , ...

  10. 初学mysql数据库

    package com.conn; import java.sql.Connection; import java.sql.DriverManager; public class Conn { pub ...