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. printf 输出格式设置\033[47\033[5m 与-8.8s

    摘要:在使用linux终端命令的时候,我们可以看到像more命令,它的显示方式与一般的字符串不同,是用了反显.同样,linux C下printf还有很多其他不常见的格式化输出形式.本文主要为你盘点这些 ...

  2. 【LeetCode 33】搜索旋转排序数组

    题目链接 [题解] 会发现旋转之后,假设旋转点是i 则0..i-1是递增有序的.然后i..len-1也是递增有序的. 且nums[i..len-1]<nums[0]. 而nums[1..i-1] ...

  3. Navicat12破解教程

    Navicat12破解教程 1.下载Navicat12 并安装,打开Navicat12 点击14天试用,关闭软件 2.下载注册机: 个人百度网盘(版本更新可能不及时):https://pan.baid ...

  4. Spring学习笔记第一篇——初识Spring

    1.简单介绍 spring的ioc底层是先配置xml文件,接着创建工厂,利用dom4j解析配置文件,最后通过反射完成.大概步骤差不多这样,这些具体代码spring帮你完成了.现在我们只需要配置xml和 ...

  5. 兼容iphone x刘海的正确姿势

    在 ios 11 中我们可以使用 viewport-fit=cover + safe-area-inset-*. 那么是不是 ios11 以下就用不了这些了呢?是的,但你见过 iphone x+ 有 ...

  6. HTML5: HTML5 内联 SVG

    ylbtech-HTML5: HTML5 内联 SVG 1.返回顶部 1. HTML5 内联 SVG HTML5 支持内联 SVG. 什么是SVG? SVG 指可伸缩矢量图形 (Scalable Ve ...

  7. 原 Nginx网络架构实战学习笔记(七):nginx性能优化小总结

    文章目录 优化思路: 优化过程 Php-mysql的优化 Nginx+phjp+mysql+nginx 压力测试: 模拟 前0-10万是热数据, 10-20万是冷门数据 请求热数据 0-10,请求9次 ...

  8. Python变量的下划线

    xx: 公有变量 _x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问 __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部 ...

  9. Vue环境搭建及第一个helloWorld

    Vue环境搭建及第一个helloWorld 一.环境搭建 1.node.js环境安装配置  https://www.cnblogs.com/liuqiyun/p/8133904.html 或者 htt ...

  10. SpringBoot集成Thymeleaf模板

    1.添加起步依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId& ...