【LGR-065】洛谷11月月赛 III Div.1
T1 基础博弈练习题
分析
首先区间长度为1的情况特判,偶数必胜,奇数必败
考虑倒推,如果最后一个位置为偶数那么该位置为必败局面,否则为必胜局面
因为先手到这个位置要减去1就会让后手为偶数就赢了
那么如果是偶数显然不能走这一格,奇数那么前\(m-1\)个位置都是必败局面
可以从该位置向第一个必胜局面连边(前驱),
如果\([l\sim r]\)中\(l\)必然会到\(r\)(不然后手可以通过其它方式必胜)
也就是\(r\)在\(l\)的子树内时才会必胜
那么可以用dfs序\(O(n)\)预处理
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=1000011;
struct node{int y,next;}e[N];
int A,B,C,P,n,m,Q,typ,dfn[N],Fa[N],tot,k,as[N],rfn[N],a[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void add(int x,int y){e[++k]=(node){y,as[x]},as[x]=k;}
inline signed rnd(){return A=(A*B+C)%P;}
inline void dfs(int x){
dfn[x]=++tot;
for (rr int i=as[x];~i;i=e[i].next)
dfs(e[i].y);
rfn[x]=tot;
}
signed main(){
memset(as,-1,sizeof(as));
n=iut(),m=iut(),Q=iut(),typ=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
if (typ) A=iut(),B=iut(),C=iut(),P=iut();
for (rr int i=1;i<=n;++i){
rr int Le=i>m?i-m-1:0;
if (a[i]&1){
if (a[Le]&1) Fa[i]=Le,add(Le,i);//两个位置都是奇数必胜
else Fa[i]=Fa[Le],add(Fa[Le],i);//找到这个点的前驱
}else{
if (a[i-1]&1) Fa[i]=i-1,add(i-1,i);//直接连上一个位置
else Fa[i]=Fa[i-1],add(Fa[i-1],i);//同理
}
}
dfs(0);
rr unsigned sum=0,ans=0;
for (rr int i=1,l,r;i<=Q;++i){
sum+=i+i-1;
if (typ){
l=rnd()%n+1,r=rnd()%n+1;
if (l>r) l^=r,r^=l,l^=r;
}else l=iut(),r=iut();
if (l==r) ans+=a[l]&1?0:sum;
else if (dfn[l]>dfn[r]||dfn[r]>rfn[l])
ans+=sum;
}
return !printf("%u",ans);
}
T2 基础最优化练习题
分析
贪心,对于\(w\)是负数,肯定要选择减\(k\),因为减\(k\)不会影响以后的限制
如果是正数,还要考虑限制,首先先加上\(k\),然后如果超过限制往当前\(a_i\)移动,
首先最多可以减\(2k\),然后我肯定要选\(w\)最小的位置,那可以用堆处理,
找出\(w\)最小的位置,提取它能减小的次数,把答案减小,如果次数还有重新放回堆里,时间复杂度\(O(nlogn)\)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
typedef long long lll;
const int N=1000011;
struct rec{
lll w; int c;
bool operator <(const rec &t)const{
return w<t.w;
}
}heap[N];
int a[N],n,k,now,cnt; lll w[N],ans;
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline void Push(rec w){
heap[++cnt]=w;
rr int x=cnt;
while (x>1){
if (heap[x]<heap[x>>1])
swap(heap[x>>1],heap[x]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[cnt--];
rr int x=1;
while ((x<<1)<=cnt){
rr int y=x<<1;
if (y<cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[y],heap[x]),x=y;
else return;
}
}
signed main(){
n=iut(),k=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=1;i<=n;++i) w[i]=iut();
for (rr int i=n-1;i;--i) w[i]+=w[i+1];
for (rr int i=1;i<=n;++i){
if (w[i]>0) ans+=w[i]*k,now+=k,Push((rec){w[i],k<<1});
else ans-=w[i]*k,now-=k;
while (now>a[i]){
rr rec t=heap[1]; Pop();
rr int less=min(now-a[i],t.c);
ans-=less*t.w,now-=less;
if (less<t.c) Push((rec){t.w,t.c-less});
}
}
return !printf("%lld",ans);
}
T3 基础函数练习题
分析
如果学过笛卡尔树就知道要建一棵笛卡尔树(\(O(n)\)单调栈)
等于说两头往它们的LCA跳,分别处理,以左端点为例

如果处理2~4,红色边才是应该找的,假设搜索到点\(x\)
这需要对之前的倍增数组有修改,比如说准备访问右端点时,父亲应该定为该点的父亲。
需要预处理\(x\)到\(f[x][i]\)的\(w\)总和(常规操作)和
\(f[x][i]\)的子树\(w\)总和(不包括\(x\)的左子树,右端点为右子树)(避免算重)
然后倍增的道理就是拼凑结果,也没有什么好说的了
可惜O2MLE了(常数小内存大直接暴毙)
代码
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#define rr register
using namespace std;
typedef long long lll;
const int N=500011;
lll s[N],ans[N],lin[N][19],sub[N][19];
int root,Lc[N],Rc[N],bas,w[N],f[N][19];
int a[N],n,Q,dep[N],B,l[N],r[N],LCA[N],st[N];
inline signed iut(){
rr int ans=0,f=1; rr char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans*f;
}
inline void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline lll max(lll a,lll b){return a>b?a:b;}
inline signed DiKaEr(){
rr int top=0; a[0]=2e9;
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=1,lst=0;i<=n;++i){
while (a[st[top]]<a[i]) --top;
if (top<lst) Lc[i]=st[top+1];
if (top) Rc[st[top]]=i;
st[lst=++top]=i;
}
for (rr int i=0;i<=n;++i) a[i]=0;
for (rr int i=1;i<=n;++i) a[Lc[i]]=a[Rc[i]]=1;
for (rr int i=1;i<=n;++i) if (!a[i]) return i;
return 0;
}
inline void dfs1(int x,int fa){
dep[x]=dep[fa]+1,f[x][0]=fa;
for (rr int i=0;i<B&&f[x][i];++i)
f[x][i+1]=f[f[x][i]][i];
if (Lc[x]) dfs1(Lc[x],x);
if (Rc[x]) dfs1(Rc[x],x);
s[x]=max(s[Lc[x]],s[Rc[x]])+w[x];
}
inline signed lca(int x,int y){
if (dep[x]<dep[y]) x^=y,y^=x,x^=y;
for (rr int i=B;~i;--i)
if (dep[f[x][i]]>=dep[y]) x=f[x][i];
if (x==y) return x;
for (rr int i=B;~i;--i)
if (f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
inline void dfs2(int x,bool z){
lin[x][0]=w[x],sub[x][0]=w[x]+(z?s[Lc[x]]:s[Rc[x]]);
for (rr int i=0;i<B&&f[x][i];++i){
f[x][i+1]=f[f[x][i]][i],lin[x][i+1]=lin[x][i]+lin[f[x][i]][i],
sub[x][i+1]=max(lin[f[x][i]][i]+sub[x][i],sub[f[x][i]][i]);
}
if (Lc[x]) f[Lc[x]][0]=z?f[x][0]:x,dfs2(Lc[x],z);
if (Rc[x]) f[Rc[x]][0]=z?x:f[x][0],dfs2(Rc[x],z);
}
inline lll query(int x,int y){
rr lll ans=0;
for (rr int i=B;~i;--i)
if (dep[f[x][i]]>=dep[y]){
ans=max(ans+lin[x][i],sub[x][i]);
x=f[x][i];
}
return ans;
}
signed main(){
n=iut(),Q=iut(),root=DiKaEr(); for (B=0;(2<<B)<=n;++B);
for (rr int i=1;i<=n;++i) w[i]=iut(); dfs1(root,0);
for (rr int i=1;i<=Q;++i) l[i]=iut(),r[i]=iut();
for (rr int i=1;i<=Q;++i) LCA[i]=lca(l[i],r[i]);
for (rr int i=1;i<=Q;++i) ans[i]=-1e16;
memset(f,0,sizeof(f)),dfs2(root,0);
for (rr int i=1;i<=Q;++i) ans[i]=max(ans[i],query(l[i],LCA[i])+w[LCA[i]]);
memset(f,0,sizeof(f)),dfs2(root,1);
for (rr int i=1;i<=Q;++i) ans[i]=max(ans[i],query(r[i],LCA[i])+w[LCA[i]]);
for (rr int i=1;i<=Q;++i){
if (ans[i]<0) putchar('-'),ans[i]=-ans[i];
print(ans[i]),putchar(10);
}
return 0;
}
T4 基础数论函数题
分析
求区间LCM对\(10^9+7\)取模,多组数据多组询问,
\(n,T,Q\leq 300,a\leq 2^{60}\)
分析
首先\(2^{60}\)不能接受,因为除法和取模存在冲突,这就要求没有除法
那可以将LCM转换为区间积,也就是用当前数剔除之前存在的GCD,
那么就可以获得\(O(Tqn^2)\)的代码,把在线换成离线分治,时间复杂度是\(O(Tn^2)\)
回过头看一下怎样剔除GCD,可以用取模的方式实现
至于为什么没有\(GCD\)的常数,给出一部分代码就知道了
for (int j=mid+1;j<=r;++j) c[j]=mul(c[j-1],b[j],b[i]);//在后半部分剔除b[i]的约数
lll GCD=gcd(c[r],b[i]);//gcd(b[i],b[mid+1]*b[mid+2]*...*b[r-1]*b[r])
for (int j=r-1;j>=mid;--j)
if (c[j]%GCD){//gcd(b[j+1],GCD)必然不等于1
lll Gcd=gcd(c[j],GCD);
b[j+1]=b[j+1]/(GCD/Gcd),GCD=Gcd;//消约数
}
显然只有log个位置会被算上
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long lll;
const lll mod=1000000007;
lll a[301],b[301],c[301];
int ans[301][301],n,Q;
inline lll iut(){
rr lll ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline lll gcd(lll a,lll b){return b?gcd(b,a%b):a;}
inline lll mul(lll a,lll b,lll mod){
a=a%mod,b=b%mod;
rr lll t=(long double)a*b/mod,ans=a*b-t*mod;
ans=ans<0?ans+mod:ans,ans=ans>=mod?ans-mod:ans;
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline void divi(int l,int r){
if (l==r){
ans[l][r]=a[l]%mod;
return;
}
rr int mid=(l+r)>>1;
divi(l,mid),divi(mid+1,r);
rr lll t,t1=1,t2=1;
for (rr int i=mid;i>=l;--i){
b[i]=a[i],t=1;
for (rr int j=i+1;j<=mid;++j)
t=mul(t,b[j],b[i]);
b[i]=b[i]/gcd(b[i],t);
}
for (rr int i=mid+1;i<=r;++i){
b[i]=a[i],t=1;
for (rr int j=i-1;j>mid;--j)
t=mul(t,b[j],b[i]);
b[i]=b[i]/gcd(b[i],t);
}
for (rr int i=mid;i>=l;--i){
t2=t1=b[i]%mod*t1%mod,c[mid]=1;
for (rr int j=mid+1;j<=r;++j)
c[j]=mul(c[j-1],b[j],b[i]);
rr lll GCD=gcd(c[r],b[i]);
for (rr int j=r-1;j>=mid;--j)
if (c[j]%GCD){
rr lll Gcd=gcd(c[j],GCD);
b[j+1]=b[j+1]/(GCD/Gcd),GCD=Gcd;
}
for (rr int j=mid+1;j<=r;++j)
t2=ans[i][j]=b[j]%mod*t2%mod;
}
}
signed main(){
for (rr int Test=iut();Test;--Test){
n=iut(),Q=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
divi(1,n);
for (rr int l,r;Q;--Q,putchar(10))
l=iut(),r=iut(),print(ans[l][r]);
}
return 0;
}
【LGR-065】洛谷11月月赛 III Div.1的更多相关文章
- 【LGR-065】洛谷11月月赛 III Div.2
临近$CSP$...... 下午打了一发月赛,感觉很爽. 非常菜的我只做了前两题......然而听说前两题人均过...... 写法不优秀被卡到$#1067$...... T1:基础字符串练习题: 前缀 ...
- 【LGR-062】洛谷10月月赛 III div.2 (A-C)
前言 100+100+46+0=246pts 300多名 以后每次比赛都要有进步哦!qwq 小D与笔试 水题 Code #include<algorithm> #include<io ...
- 洛谷 11 月月赛 I Div.2 A [Kubic] Addition 题解
Content 你有一个长度为 \(n\) 的序列 \(a\).你可以执行 \(n-1\) 次操作,每次操作中你可以选择一个位置 \(i\),并删除 \(a_i\) 和 \(a_{i+1}\),再在原 ...
- 「P4996」「洛谷11月月赛」 咕咕咕(数论
题目描述 小 F 是一个能鸽善鹉的同学,他经常把事情拖到最后一天才去做,导致他的某些日子总是非常匆忙. 比如,时间回溯到了 2018 年 11 月 3 日.小 F 望着自己的任务清单: 看 iG 夺冠 ...
- 「P4994」「洛谷11月月赛」 终于结束的起点(枚举
题目背景 终于结束的起点终于写下句点终于我们告别终于我们又回到原点…… 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演.如果这次 NO ...
- 「LuoguP4995」「洛谷11月月赛」 跳跳!(贪心
题目描述 你是一只小跳蛙,你特别擅长在各种地方跳来跳去. 这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 ii 块的石头高度为 h_ihi,地面的高度是 h_0 = 0 ...
- 洛谷11月月赛(284pts rank85)
https://www.luogu.org/contestnew/show/12006 我是比赛完后在去写的 这是我第一次打洛谷月赛,之前一次是比赛完才去看而且写了第一题就没写后面的了 284分,太水 ...
- 洛谷11月月赛round.1
太感动了#2 thwfhk 240 (801ms) 100 100 40 又一张明信片,话说10月的怎么还没收到 P2246 SAC#1 - Hello World(升级版) 题目背景 一天, ...
- 洛谷11月月赛round.2
P3414 SAC#1 - 组合数 题目背景 本题由世界上最蒟蒻最辣鸡最撒比的SOL提供. 寂月城网站是完美信息教室的官网.地址:http://191.101.11.174/mgzd . 题目描述 辣 ...
- 洛谷11月月赛题解(A-C)
心路历程 辣鸡T3卡我1.5h题意,要不是最后nlh跟我解释了一下大样例估计这次是真凉透了.. A P4994 终于结束的起点 打出暴力来发现跑的过最大数据?? 保险起见还是去oeis了一波,然后被告 ...
随机推荐
- Programming Abstractions in C阅读笔记:p293-p302
<Programming Abstractions in C>学习第73天,p293-p302总结,总计10页. 一.技术总结 1.时间复杂度 (1)quadratic time(二次时间 ...
- JavaScript的引入并执行-包含动态引入与静态引入
JavaScript的引入并执行-包含动态引入与静态引入 JavaScript引入方式 html文件需要引入JavaScript代码,才能在页面里使用JavaScript代码. 静态引入 行内式 直接 ...
- 双层循环练习,pass_break_continue,和for循环---day06
1.双层循环练习 2.pass_break_continue pass:在代码块中无代码可写时,可用pass占位 break:终止当前循环,只能应用在循环里 continue:跳过当前循环,从下一次开 ...
- 数据分析day02
案例 需求:双均线策略制定 1.使用tushare包获取某股票的历史行情数据 2.计算该股票历史数据的5日均线和30日均线 - 什么是均线? - 对于每一个交易日,都可以计算出前N天的移动平均值,然后 ...
- 【LeetCode二叉树#05】平衡二叉树
力扣题目链接(opens new window)](https://leetcode.cn/problems/balanced-binary-tree/) 给定一个二叉树,判断它是否是高度平衡的二叉树 ...
- 【Azure 环境】调用Azure RunCommand 的REST API 设置虚拟机的环境变量(SetEnvironmentVariable)
问题描述 在Azure VM的门户页面中,可以通过 RunPowerShellScript来执行PowerShell脚本,如下图: 那么,如何使用REST API 在Azure VM中执行PowerS ...
- C++11新特性的一些用法举例②
/** C++11 * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝构造函数 拷贝赋值重载 取地址重载 const 取地址重载 最后重要的是前4个,后两个用处不大.默认 ...
- 面试准备不充分,被Java守护线程干懵了,面试官主打一个东西没用但你得会
写在开头 面试官:小伙子请聊一聊Java中的精灵线程? 我:什么?精灵线程?啥时候精灵线程? 面试官:精灵线程没听过?那守护线程呢? 我:守护线程知道,就是为普通线程服务的线程嘛. 面试官:没了?守护 ...
- Openssl命令详解 - 证书篇
生成自签证书 # 设置CA证书subject CA_SUBJ="/C=CN/ST=ShanDong/L=JiNan/O=sec/OU=sec/CN=www.hxy.com/emailAddr ...
- (完美解决)chatGPT登陆正常却无法发送消息
这几天要写关于项目的文字性材料,登陆上chatgpt,结果发现登陆正常,各方面都正常,但是点击发送消息就会不停转圈圈,无法发送出去,然后联想到之前看到朋友圈有人说chatGPT崩了,就没多在意,结果今 ...