T1矩阵游戏

数学题。首先这一列这一行先乘还是后乘对最后答案没有影响。a[i][j]表示矩阵中原始的值,h[i]表示i行的累乘,l[i]表示i列的累乘。易得ans=Σa[i][j]*h[i]*l[i]

化简:

ans= Σa[i][j]*h[i]*l[j]=Σh[i]*Σa[i][j]*l[j]

a[i][j]为矩阵的初始值,公差为1的等差数列

以j==3为例 Σa[i][j]*l[j]=a[i][1]*l[1]+a[i][2]*l[2]+a[i][3]*l[3]
                    =a[i][1]*l[1]+(a[i][1]+1)*l[2]+(a[i][1]+2)*l[3]
                    =a[i][1]*l[1]+a[i][1]*l[2]+a[i][1]*l[3]+0*l[1]+1*l[2]+2*l[3]
                    =a[i][1]*(l[1]+l[2]+l[3])+0*l[1]+1*l[2]+2*l[3]

设sum=(l[1]+l[2]+l[3])。Σa[i][j]*l[j]=a[i][1]*sum+0*l[1]+1*l[2]+2*l[3]

a[i][1]=(i-1)*m+1 -->  Σa[i][j]*l[j]=((i-1)*m+1)*sum+0*l[1]+1*l[2]+2*l[3]=(i-1)*m*sum+0*l[1]+1*l[2]+2*l[3]+sum

把sum回带 得Σa[i][j]*l[j]=(i-1)*m*sum+1*l[1]+2*l[2]+3*l[3]

设sumlj=1*l[1]+2*l[2]+3*l[3]...

Σa[i][j]*l[j]=(i-1)*m*sum+sunlj

综上,ans=Σh[i]*((i-1)*m*sum+sumlj)

#include<iostream>
#include<cstdio>
#define mod 1000000007
#define ll long long
using namespace std;
ll n,m,k,ans,h[],l[],sumlj,suml;
ll read()
{
register ll aa=,bb=;register char cc=getchar();
while(cc>''||cc<''){if(cc=='-') bb=-;cc=getchar();}
while(cc<=''&&cc>=''){aa=aa*+cc-'';cc=getchar();}
return aa*bb;
}
int main()
{
n=read(),m=read(),k=read();
for(register ll i=;i<=n;i++) h[i]=;
for(register ll i=;i<=m;i++) l[i]=;
register char ch[];register ll x,y;
for(register ll i=;i<=k;i++){
scanf("%s",ch);
x=read();y=read();
if(ch[]=='R') h[x]=h[x]*y%mod;
else l[x]=l[x]*y%mod;
}
for(int i=;i<=m;i++) suml=(suml+l[i])%mod,sumlj=(sumlj+l[i]*i%mod)%mod;
for(int i=;i<=n;i++) ans=(ans+((i-)*m%mod*suml%mod+sumlj)%mod*h[i]%mod)%mod;
printf("%lld\n",ans);
return ;
}

矩阵游戏

T2 跳房子

正解是找循环节,每次跳循环节(码量挺大),在我调了一天也没调出来后我就放弃了。

另一种解法是用线段树维护。

把每一列当作一个节点,每个节点(列)里维护这一列的每一行跳一下会跳到哪,上面的区间里维护从l列的某一行到r+1列哪一行,对于每一次询问,区间查询找到跑一圈的情况,用类似快速幂的东西让他跑k/m圈,剩下的区间查询。这个过程中我们其实已经把从当前列的任意位置开跑的情况都已经处理出来了,只需要查询对应行即可。

change操作只会影响上一列的三个点,但由于第一行和最后一行的情况不好处理,我们可以暴力把这一整列都改了,反正没T。。。线段树单点修改就可以了。

需要注意的是那个类似于初始矩阵的东西,他的含义是从这一行跳会回到这一行,所以c[i]=i 。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,Q,x,y,a[][],jump[],huan,hlen,vis[],bx,by,xa,ya;
char ch[];
struct node
{
int l,r,c[];
}t[];
struct nede
{
int c[];
void init(){for(int i=;i<=n;i++) c[i]=i;}
}ans;
void bl()
{
if(by==m) by=;
else by++;
if(bx==){
if(a[bx][by]>a[bx+][by]&&a[bx][by]>a[n][by]) bx=bx;
else if(a[bx+][by]>a[bx][by]&&a[bx+][by]>a[n][by]) bx=bx+;
else if(a[n][by]>a[bx][by]&&a[n][by]>a[bx+][by]) bx=n;
}
else if(bx==n){
if(a[bx][by]>a[bx-][by]&&a[bx][by]>a[][by]) bx=bx;
else if(a[bx-][by]>a[bx][by]&&a[bx-][by]>a[][by]) bx=bx-;
else if(a[][by]>a[bx][by]&&a[][by]>a[bx-][by]) bx=;
}
else{
if(a[bx][by]>a[bx+][by]&&a[bx][by]>a[bx-][by]) bx=bx;
else if(a[bx+][by]>a[bx][by]&&a[bx+][by]>a[bx-][by]) bx=bx+;
else if(a[bx-][by]>a[bx][by]&&a[bx-][by]>a[bx+][by]) bx=bx-;
}
}
void update(int x)
{
for(int i=;i<=n;i++) t[x].c[i]=t[x*+].c[t[x*].c[i]];
}
void build(int x,int l,int r)
{
t[x].l=l;t[x].r=r;
if(l==r){
for(int i=;i<=n;i++){
bx=i;by=l;
bl();
t[x].c[i]=bx;
}
return;
}
int mid=(l+r)>>;
build(x*,l,mid);
build(x*+,mid+,r);
update(x);
}
void mul(nede a,node b)
{
for(int i=;i<=n;i++) ans.c[i]=b.c[a.c[i]];
}
void query(int x,int l,int r)
{
if(l<=t[x].l&&r>=t[x].r){
mul(ans,t[x]);
return;
}
int mid=(t[x].l+t[x].r)>>;
if(l<=mid) query(x*,l,r);
if(r>mid) query(x*+,l,r);
}
void change(int x,int pos)
{
if(t[x].l==t[x].r&&t[x].l==pos){
for(int i=;i<=n;i++){
bx=i;by=pos;
bl();
t[x].c[i]=bx;
}
return;
}
int mid=(t[x].l+t[x].r)>>;
if(pos<=mid) change(x*,pos);
else change(x*+,pos);
update(x);
}
nede mult(nede a,nede b)
{
nede as;as.init();
for(int i=;i<=n;i++) as.c[i]=b.c[a.c[i]];
return as;
}
nede qpow(nede x,int p)
{
nede as;as.init();
while(p){
if(p&) as=mult(as,x);
x=mult(x,x);
p>>=;
}
return as;
}
int main()
{
// freopen("jump1.in","r",stdin);
// freopen("2.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&a[i][j]);
build(,,m);
scanf("%d",&Q);int xx,yy,zz;
xa=;ya=;
while(Q--){
scanf("%s",ch);
if(ch[]=='m'){
scanf("%d",&xx);
ans.init();
query(,ya,m);
if(ya!=) query(,,ya-);
ans=qpow(ans,xx/m);
int jp=xx%m;
if(jp){
if(ya+jp-<=m) query(,ya,ya+jp-);
else query(,ya,m),query(,,ya+jp-m-);
}
xa=ans.c[xa];ya=(ya+xx-)%m+;
printf("%d %d\n",xa,ya);
}
else{
scanf("%d%d%d",&xx,&yy,&zz);
a[xx][yy]=zz;
if(yy==) change(,m);
else change(,yy-);
}
}
return ;
}

跳房子

T3 优美序列

1.两个好区间的交集也是好区间,所以一个区间向右找到的第一个好区间的右端点就是这个询问区间答案的右端点。

2.一个[l,r]的好区间里,差的绝对值为1的二元组有r-l个。因为把这个区间排序,他肯定是连续的。所以这个可以转化为l+num(二元组)=r,可以当做我们判定一个区间是否为好区间的依据。前边的都已经处理好了,那么当前点i只可能与a[i]+1或a[i]-1构成二元组。包含pos的区间都可以得到1的贡献,所以[1,pos]的区间都可以+1。

离线处理,把所有询问按右边界的大小放进小根堆里。建一棵线段树存区间l+num的最大值,并且维护这个最大值出现的最大位置(l最靠右保证最短)。

l+num只有小于或等于这两种可能,所以只可能是max=r,所以最大值就可以。

每次把以i为右端点的询问倒进待询问的小根堆里,查询[1,l]中是否有满足条件的,满足就找到了答案,不满足了就直接break

至于为什么要把所有询问按右边界的大小放进小根堆里,是因为待询问中r最小的都不符合了,那其他更不可能符合,画图感受一下。(右边不可能比左边多)

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
struct node
{
int l,r,id;
friend bool operator < (node a,node b){
return a.l==b.l?a.r>b.r:a.l<b.l;
}
}h[],ans[];
struct tree
{
int l,r,mx,pos,lz;
}t[];
int n,m,a[],pos[];
vector<node> ve[];
priority_queue<node>q;
void update(int x)
{
t[x].mx=max(t[x*].mx,t[x*+].mx);
t[x].pos=t[x*].mx>t[x*+].mx?t[x*].pos:t[x*+].pos;
}
void build(int x,int l,int r)
{
t[x].l=l;t[x].r=r;
if(l==r){
t[x].mx=l;
t[x].pos=l;
return;
}
int mid=(l+r)>>;
build(x*,l,mid);
build(x*+,mid+,r);
update(x);
}
void pushdown(int x)
{
if(t[x].lz){
t[x*].mx+=t[x].lz;t[x*+].mx+=t[x].lz;
t[x*].lz+=t[x].lz;t[x*+].lz+=t[x].lz;
t[x].lz=;
}
}
void add(int x,int l,int r)
{
if(l<=t[x].l&&r>=t[x].r){
t[x].mx++;
t[x].lz++;
return;
}
pushdown(x);
int mid=(t[x].l+t[x].r)>>;
if(l<=mid) add(x*,l,r);
if(r>mid) add(x*+,l,r);
update(x);
}
int query(int x,int l,int r,int w)
{
if(t[x].mx<w) return -;
if(l<=t[x].l&&r>=t[x].r) return t[x].pos;
pushdown(x);
int mid=(t[x].l+t[x].r)>>,as=-;
if(l<=mid) as=max(as,query(x*,l,r,w));
if(r>mid) as=max(as,query(x*+,l,r,w));
return as;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d%d",&h[i].l,&h[i].r);
h[i].id=i;
ve[h[i].r].push_back(h[i]);
}
build(,,n);
for(int i=;i<=n;i++){
if(a[i]>&&pos[a[i]-]<i) add(,,pos[a[i]-]);
if(a[i]<n&&pos[a[i]+]<i) add(,,pos[a[i]+]);
for(int j=;j<ve[i].size();j++) q.push(ve[i][j]);
while(q.size()){
node hh=q.top();
int as=query(,,hh.l,i);
if(as==-) break;
ans[hh.id].l=as;ans[hh.id].r=i;
q.pop();
}
}
for(int i=;i<=m;i++) printf("%d %d\n",ans[i].l,ans[i].r);
return ;
}

优美序列

这个出题人好像很喜欢线段树和网格嘞

8.5 NOIP模拟测试13 矩阵游戏+跳房子+优美序列的更多相关文章

  1. NOIP模拟测试13「矩阵游戏&#183;跳房子&#183;优美序列」

    矩阵游戏 考试时思路一度和正解一样,考试到最后还是打了80分思路,结果80分打炸了只得了40分暴力分 题解 算出来第一列的总值,每次通过加每两列之间的差值得出下一列的总值 算第一列我们只需要让当前点* ...

  2. NOIP模拟测试13

    考得还算可以,T3还有提升空间(没看清题&&样例没过 拿了4分). 期望得分:80+40+0=120 实际得分:80+85+4=169 一脸黑线.....是数据比较水的原因,T2分都比 ...

  3. 2019.8.5 NOIP模拟测试13 反思总结【已更新完毕】

    还没改完题,先留个坑. 放一下AC了的代码,其他东西之后说… 改完了 快下课了先扔代码 跑了跑了 思路慢慢写 来补完了[x 刚刚才发现自己打错了标题 这次考试挺爆炸的XD除了T3老老实实打暴力拿了52 ...

  4. 8.5 NOIP 模拟测试 13

    今天的考试说实话T1很简单没A,我是傻X.T2T3难得一批,但是暴力的分还是拿了! 总结一下就是:骗分过样例,暴力出奇迹!只要瞎搞就行了! 话说现在终于不像之前那么傻了,终于知道打暴力了,因为之前暴力 ...

  5. NOIP模拟测试17&18

    NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...

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

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

  7. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  8. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  9. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

随机推荐

  1. multer 文件后缀名

    我的代码是这样写的. var storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uplo ...

  2. STM32移植ROS--发布超声波信息

    前言:之前ROS跟单片机的底层通讯主要是通过串口自定的协议来做,比如官网提供的arduino串口驱动一样,需要ROS往下发一个指令,单片机再回传一个指令,要写一大堆的协议,这样很麻烦,效率也比较低, ...

  3. Flask-Moment本地化日期和时间

    moment.js客户端开源代码库,可以在浏览器中渲染日期和时间.Flask-Moment是一个flask程序扩展,能把moment.js集成到Jinja2模板中. 1.安装 pip install ...

  4. LCM Walk HDU - 5584

    A frog has just learned some number theory, and can't wait to show his ability to his girlfriend. No ...

  5. CompletableFuture1

    public class CompletableFutureTest { public static void main(String[] args) throws Exception { test5 ...

  6. 钉钉SDK使用。

    (1)到 https://open-doc.dingtalk.com/microapp/faquestions/vzbp02 下载SDK (2)引入 using DingTalk.Api; using ...

  7. 利用正则来查找字符串中第n个匹配字符索引

    1.string.IndexOf()方法可以获得第一个匹配项的索引 2.要获取第n个匹配项的索引:  方法1:利用IndexOf方法循环获取. 方法2:用正则来查找. System.Text.Regu ...

  8. python3字符串常用操作练习

    练习一下字符串的常用操作 #-*- coding:utf-8 -*- #字符串的常用操作 str = "1111 Hell :wo:rld! " #删除头尾所有指定字符串,默认移除 ...

  9. jsonHelper帮助类

    使用前,需引用开源项目类using Newtonsoft.Json 链接:https://pan.baidu.com/s/1htK784XyRCl2XaGGM7RtEg 提取码:gs2n using ...

  10. linux应用管理

    desktop文件的几个位置: /usr/share/applications ~/.local/share/applications /usr/local/share/applications li ...