A.矩阵游戏

其实挺水的?

考场上根本没有管出题人的疯狂暗示(诶这出题人有毛病吧这么简单的东西写一大堆柿子),而且推公式能力近乎没有,所以死掉了。

很显然乘法有交换率结合率所以操作顺序对最终结果没什么影响对吧,垃圾如我都能一眼看出来。

统计一下每行总共乘的倍数$h_i$,每列总共乘的倍数$l_i$,

之后考虑$O(n^2)$怎么求出答案:$ans=\sum \limits _{i=1}^{n}h_i \sum \limits _{j=1}^{m}l_j\times((i-1)\times m+j)$

化简一下:$\sum \limits_{i=1}^{n}h_i \sum \limits_{j=1}^{m} l_j\times (i-1)\times m+l_j\times j$

继续:$\sum h_i\sum l_j\times j + \sum h_i \times (i-1)\times m \sum l_j$

显然可以$O(n)$了吧

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+;
const int N=,M=;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
int n,m,K;
ll hang[N],lie[N],sum,ans;
int toth,totl; int main()
{
n=read();m=read();K=read();
for(int i=;i<=n;i++)hang[i]=;
for(int i=;i<=m;i++)lie[i]=;
char str[];
for(int i=;i<=K;i++)
{
scanf("%s",str);
if(str[]=='R')
{
int num=read();ll val=1LL*read();
(hang[num]*=val)%=mod;
}
else
{
int num=read();ll val=1LL*read();
(lie[num]*=val)%=mod;
}
}
ll sumhang=,ans=;
for(int i=;i<=n;i++)
{
ll now=1LL*(i-)*m+;
now%=mod;
sum+=now*hang[i]%mod,sum%=mod;
sumhang+=hang[i],sumhang%=mod; }
for(int i=;i<=m;i++)
{
ans+=sum*lie[i]%mod,ans%=mod;
sum+=sumhang,sum%=mod;
}
cout<<ans<<endl;
return ;
}

B.跳房子

RT,跳楼题

我这样的菜b就只能想到大模拟,然而大佬就是能想出来线段树+置换群+快速幂的做法。

(我就是没脸我就要粘blog)

关于代码实现,说几点细节。

可以让$a[0][j]=a[n][j],a[n+1][j]=a[1][j]$,这样写找下一步的函数就比较简单,修改的时候特判一下就好。

置换的运算:$res[i]=b[a[i]]$,可以直接丢到快速幂里跑实现倍增的效果。

询问的时候暴力部分记得分类全,考虑它是否能越界。

query函数如果直接把映射当参传的话记得取地址。

C.优美序列

部分分还是很多而且比较好拿的,由于值域范围比较友好我们可以记录一下每个编号对应的位置$pos[]$,然后用数据结构分别维护$a[]$和$pos[]$序列上的最大最小值。之后对于每个询问$[l,r]$,先查询$[l,r]$的编号最大最小值,然后就得到了一段值域,再在这段值域上查询位置的最左和最右端点。如果最左和最右端点都在$[l,r]$内(事实上,只有可能查出来就是$[l,r]$,在它之内是不可能的),那么$[l,r]$即为所求。否则,将新得到的最左最右端点作为新的$l$和$r$再次询问。重复这个过程,最后一定能得到解。

这种办法考场上就已经码出来了,后来又分别用线段树和ST表实现了一下。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=; const int L=<<|;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
int a[N],n,m,pos[N];
#define ls(k) k<<1
#define rs(k) k<<1|1
int maxx[N<<],minn[N<<],pmax[N<<],pmin[N<<];
int lastl,lastr;
void build(int k,int l,int r)
{
if(l==r)
{
maxx[k]=minn[k]=a[l];
pmax[k]=pmin[k]=pos[l];
return ;
}
int mid=l+r>>;
build(ls(k),l,mid);
build(rs(k),mid+,r);
maxx[k]=max(maxx[ls(k)],maxx[rs(k)]);
minn[k]=min(minn[ls(k)],minn[rs(k)]);
pmax[k]=max(pmax[ls(k)],pmax[rs(k)]);
pmin[k]=min(pmin[ls(k)],pmin[rs(k)]);
}
int qmax(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)
{
return maxx[k];
}
int mid=l+r>>,res=;
if(L<=mid)res=max(res,qmax(ls(k),l,mid,L,R));
if(R>mid)res=max(res,qmax(rs(k),mid+,r,L,R));
return res;
}
int qmin(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)
{
return minn[k];
}
int mid=l+r>>,res=0x3f3f3f3f;
if(L<=mid)res=min(res,qmin(ls(k),l,mid,L,R));
if(R>mid)res=min(res,qmin(rs(k),mid+,r,L,R));
return res;
}
int qpmax(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)
{
return pmax[k];
}
int mid=l+r>>,res=;
if(L<=mid)res=max(res,qpmax(ls(k),l,mid,L,R));
if(R>mid)res=max(res,qpmax(rs(k),mid+,r,L,R));
return res;
}
int qpmin(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)
{
return pmin[k];
}
int mid=l+r>>,res=0x3f3f3f3f;
if(L<=mid)res=min(res,qpmin(ls(k),l,mid,L,R));
if(R>mid)res=min(res,qpmin(rs(k),mid+,r,L,R));
return res;
}
int main()
{
n=read();
for(int i=;i<=n;i++)
a[i]=read(),pos[a[i]]=i;
build(,,n);
m=read();
while(m--)
{
int l=read(),r=read();
if(l==r)
{
printf("%d %d\n",l,r);
continue;
}
else if(l==&&r==n)
{
printf("%d %d\n",,n);
continue;
}
lastl=lastr=;
while(l!=lastl||r!=lastr)
{
lastl=l;lastr=r;
int maxval=qmax(,,n,l,r);
int minval=qmin(,,n,l,r);
l=qpmin(,,n,minval,maxval);
r=qpmax(,,n,minval,maxval);
}
printf("%d %d\n",l,r);
}
return ;
}

线段树:76pts

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define re register
const int N=; const int L=<<|;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
int a[N],n,m,pos[N],stmax[N][][],lg[N]={-},stmin[N][][];
int lastl,lastr;
void ini()
{
for(re int i=;i<=n;i++)
stmax[i][][]=stmin[i][][]=a[i],stmax[i][][]=stmin[i][][]=pos[i],lg[i]=lg[i>>]+;
for(re int i=;i<=lg[n];i++)
for(re int j=;j+(<<i)-<=n;j++)
for(re int k=;k<=;k++)
stmax[j][i][k]=max(stmax[j][i-][k],stmax[j+(<<(i-))][i-][k]),
stmin[j][i][k]=min(stmin[j][i-][k],stmin[j+(<<(i-))][i-][k]);
}
inline int qmax(int l,int r,int k)
{
int len=lg[r-l+];
return max(stmax[l][len][k],stmax[r-(<<len)+][len][k]);
}
inline int qmin(int l,int r,int k)
{
int len=lg[r-l+];
return min(stmin[l][len][k],stmin[r-(<<len)+][len][k]);
}
void test()
{
int L=read(),R=read();
cout<<qmax(L,R,)<<' '<<qmin(L,R,)<<endl;
}
int main()
{
n=read();
for(re int i=;i<=n;i++)
a[i]=read(),pos[a[i]]=i;
ini();
//while(1)test();
m=read();
while(m--)
{
int l=read(),r=read();
if(l==r)
{
printf("%d %d\n",l,r);
continue;
}
else if(l==&&r==n)
{
printf("%d %d\n",,n);
continue;
}
lastl=lastr=;
while(l!=lastl||r!=lastr)
{
lastl=l;lastr=r;
int maxval=qmax(l,r,);
int minval=qmin(l,r,);
l=qmin(minval,maxval,);
r=qmax(minval,maxval,);
}
printf("%d %d\n",l,r);
}
return ;
}

ST表:84pts

这种算法对于随机数据已经相当优秀了,奈何数据就是要卡你这种复杂度没有保证的qjyq。满分做法也很多,分块预处理询问/线段树扫描线/线段树建图+缩点+线段树查询并集 都可以做。我写了一下理论复杂度最低但常数最大会被第一种踩爆的建图做法。

(时间不够了先放代码题解回头补咕咕咕)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
#define ls(k) k<<1
#define rs(k) k<<1|1 const int L=<<|;
char buffer[L],*S,*T;
#define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
const int N=;
int n,m,a[N],pos[N];
struct qj
{
int l,r;
qj()
{
l=0x3f3f3f3f;r=;
}
qj(int l1,int r1)
{
l=l1,r=r1;
}
};
qj operator + (const qj &x,const qj &y)
{
return qj(min(x.l,y.l),max(x.r,y.r));
}
struct segtree
{
qj t[N];
void change(int k,int l,int r,int loc,qj val)
{
if(l==r)
{
t[k]=val;
return ;
}
int mid=l+r>>;
if(loc<=mid)change(ls(k),l,mid,loc,val);
else change(rs(k),mid+,r,loc,val);
t[k]=t[ls(k)]+t[rs(k)];
}
qj query(int k,int l,int r,int L,int R)
{
if(L<=l&&R>=r)return t[k];
int mid=l+r>>;
if(L<=mid&&R>mid)
return query(ls(k),l,mid,L,R)+query(rs(k),mid+,r,L,R);
if(L<=mid)
return query(ls(k),l,mid,L,R);
if(R>mid)
return query(rs(k),mid+,r,L,R);
}
}seg[];
vector<int> g1[N],g2[N];
void build(int k,int l,int r)
{
if(l==r)
{
pos[l]=k;
return ;
}
int mid=l+r>>;
build(ls(k),l,mid);
build(rs(k),mid+,r);
g1[k].push_back(ls(k));
g1[k].push_back(rs(k));
}
void addedge(int k,int l,int r,int L,int R,int node)
{
if(L<=l&&R>=r)
{
g1[node].push_back(k);
return ;
}
int mid=l+r>>;
if(L<=mid)addedge(ls(k),l,mid,L,R,node);
if(R>mid)addedge(rs(k),mid+,r,L,R,node);
}
qj t1[N],t2[N];
int low[N],dfn[N],ind,st[N],bel[N],scc,vis[N],top;
void tarjan(int x)
{
dfn[x]=low[x]=++ind;
vis[x]=;st[++top]=x;
int sz=g1[x].size();
for(int i=;i<sz;i++)
{
int y=g1[x][i];
if(!dfn[y])
tarjan(y),low[x]=min(low[x],low[y]);
else if(vis[y])
low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
scc++;
int now;
do
{
now=st[top--];
vis[now]=;
bel[now]=scc;
}while(now!=x);
}
}
bool v[N];
void dfs(int x)
{
if(v[x])return ;
v[x]=;
int sz=g2[x].size(),y;
for(int i=;i<sz;i++)
y=g2[x][i],dfs(y),t2[x]=t2[x]+t2[y];
}
int main()
{
n=read();build(,,n);
for(int i=;i<=n;i++)
a[i]=read();
for(int i=;i<=n;i++)
seg[].change(,,n,a[i],{i,i});
for(int i=;i<=n;i++)
{
int x=min(a[i-],a[i]),y=max(a[i-],a[i]);
t1[pos[i]]=seg[].query(,,n,x,y);
addedge(,,n,t1[pos[i]].l+,t1[pos[i]].r,pos[i]);
}
for(int i=;i<N-;i++)
if(!dfn[i])tarjan(i);
for(int x=;x<N-;x++)
{
int sz=g1[x].size();//if(!sz)continue;
for(int i=;i<sz;i++)
{
int y=g1[x][i];
if(bel[x]!=bel[y])
g2[bel[x]].push_back(bel[y]);
}
}
for(int i=;i<N-;i++)
t2[bel[i]]=t2[bel[i]]+t1[i];
for(int i=;i<=scc;i++)
dfs(i);
for(int i=;i<=n;i++)
seg[].change(,,n,i,t2[bel[pos[i]]]);
m=read();
while(m--)
{
int l=read(),r=read();
if(l==r)
{
printf("%d %d\n",l,r);
continue;
}
qj ans=seg[].query(,,n,l+,r);
printf("%d %d\n",ans.l,ans.r);
}
return ;
}

又臭又长

[NOIP模拟13]题解的更多相关文章

  1. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  2. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  3. HZOJ 20190818 NOIP模拟24题解

    T1 字符串: 裸的卡特兰数题,考拉学长讲过的原题,就是bzoj3907网格那题,而且这题更简单,连高精都不用 结论$C_{n+m}^{n}-C_{n+m}^{n+1}$ 考场上10min切掉 #in ...

  4. 「题解」NOIP模拟测试题解乱写I(29-31)

    NOIP模拟29(B) T1爬山 简单题,赛时找到了$O(1)$查询的规律于是切了. 从倍增LCA那里借鉴了一点东西:先将a.b抬到同一高度,然后再一起往上爬.所用的步数$×2$就是了. 抬升到同一高 ...

  5. HGOI NOIP模拟4 题解

    NOIP国庆模拟赛Day5 题解 T1 马里奥 题目描述 马里奥将要参加 NOIP 了,他现在在一片大陆上,这个大陆上有着许多浮空岛,并且其中一座浮空岛上有一个传送门,马里奥想要到达传送门从而前往 N ...

  6. NOIP模拟 13

    我终于又厚颜无耻地赖着没走 ...... T1 矩阵游戏 用了30hmin找规律,然后发现貌似具有交换律,然后发现貌似有通项公式,然后发现貌似每次操作对通项的影响是相同的,然后发现貌似跟N没啥关系.. ...

  7. Noip模拟13 2021.7.13:再刚题,就剁手&&生日祭

    T1 工业题 这波行列看反就非常尴尬.....口糊出所有正解想到的唯独行列看反全盘炸列(因为和T1斗智斗勇两个半小时...) 这题就是肯定是个O(n+m)的,那就往哪里想,a,b和前面的系数分开求,前 ...

  8. 8.3 NOIP 模拟12题解

    话说这次考试T1和T2是真的水,然而T1CE,T2TLE,T3CE 这不就是在侮辱我的智商啊!之前本机编译都是c++,以后要用c++11. 这次的T1就是一个大型找规律,我的规律都找出来了,但是竟然用 ...

  9. HZOJ 20190819 NOIP模拟26题解

    考试过程: 照例开题,然后觉得三道题都挺难,比昨天难多了(flag×1),T1 dp?T2 数据结构? T3 dp?事实证明我是sb然后决定先搞T2,但是,woc,这题在说什么啊,我怎么看不懂题啊,连 ...

随机推荐

  1. 关于respond.js

    作用:可以让ie8及以下支持css3的媒体查询. 有几个问题: 1.由于浏览器的安全机制,Respond.js 不能在通过 file:// 协议(打开本地HTML文件所用的协议)访问的页面上发挥正常的 ...

  2. 【Flutter学习】之 Flutter 的生命周期

    一,概述 Flutter 的生命周期分为两个部分: Widget 的生命周期 App 的生命周期 二,Widget 的生命周期 Flutter 里的 Widget 分为 StatelessWidget ...

  3. 第七周-scrum meeting

    第一部分ScrumMeeting 每个人的工作:其他人:(请填写自己的任务) 成员 任务 ISSUE链接 本周已完成的工作 本周计划完成的工作 工作中遇到的困难 关玉娇 负责登录注册界面的设计与实现 ...

  4. kubernetes session保持、容器root特权模式开启、多端口容器service 2个端口开启等设置

    session保持如何在service内部实现session保持呢?当然是在service的yaml里进行设置啦. 在service的yaml的sepc里加入以下代码: sessionAffinity ...

  5. mysql left join 用法说明

    left join中关于where和on条件的几个知识点: 1.多表left join是会生成一张临时表,并返回给用户 2.where条件是针对最后生成的这张临时表进行过滤,过滤掉不符合where条件 ...

  6. java Wrapper包装类

    什么是包装类?为什么需要包装类? 这是大家要了解的 对于java中的基本数据类型我们如果想要把当当做类来使用怎么办呢? 如果想要对这些基本数据类型直接调用一些方法来操作的话 怎么做呢? 由以上就产生了 ...

  7. 深入解读 Redis 的持久化

    Redis持久化 Java大猿帅成长手册,GitHub JavaEgg ,N线互联网开发必备技能兵器谱 Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证 Red ...

  8. 遵循PEP8风格指南

    整理来自 effective python 一 空白 1 使用space来标识缩进,而不是tab 2 和语法相关的每层缩进都使用4个空格 3 每行的字符数不应该超过79 4 对于多行的表达式,除了首行 ...

  9. LeetCode N皇后 & N皇后 II

    题目链接:https://leetcode-cn.com/problems/n-queens/ 题目链接:https://leetcode-cn.com/problems/n-queens-ii/ 题 ...

  10. 【JavaSE】运行时类型信息(RTTI、反射)

    运行时类型信息使得你可以在程序运行时发现和使用类型信息.--<Think in java 4th> **** 通常我们在面向对象的程序设计中我们经常使用多态特性使得大部分代码尽可能地少了解 ...