T1.矩阵游戏

水题。每一行最后乘的数为x[i],每一列为y[i],暴力算第一行的列的贡献,每一行的列的贡献是公差为所有列的贡献之和的等差数列,然后每一行再乘上行的贡献求和即为答案。

 //Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define Formylove return 0
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=,p=1e9+;
typedef long long LL;
typedef double db;
using namespace std;
LL n,m,k,x,y;
LL R[N],S[N],ans,bs,rs;
char o[]; template<typename T>void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} #define ANS
int main() {
#ifdef ANS
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
#endif
read(n); read(m); read(k);
int up=max(n,m);
For(i,,up) R[i]=S[i]=;
For(i,,k) {
scanf("%s",o);
read(x); read(y);
if(o[]=='R') R[x]=R[x]*y%p;
else S[x]=S[x]*y%p;
}
For(i,,m) {
rs=(rs+S[i]*i%p)%p;
bs=(bs+S[i])%p;
}
bs=bs*m%p;
For(i,,n) {
ans=(ans+rs*R[i]%p)%p;
rs=(rs+bs)%p;
}
printf("%lld\n",ans);
Formylove;
}

T2.跳房子

容易想到每次暴力找循环节地跳,复杂度是O(Q*循环节长度),很不幸的是循环节长度似乎是n*m级别的(我想证明循环节长度很小然后失败了)。

考虑分块做法,每一行为一块,预处理出从每一行的第一列开始走m步走到哪一行的第一列,每次先一行一行地跳(很长的也要按行找循环节),再一个一个跳。

如何修改,发现第一行能跳到某一个格子的点是连续的一些列,倒着回去找到一行的列(记录一个l,r)修改这些列即可。

注意修改一个点的权值后是修改可能跳到它的三个点。然后倒着回去的时候l,r因为会从上到下又从下到上蛇皮走位,把下标弄成从0开始然后l,r只管++--判断值的时候取模来处理,不然会debug到死也出不来。。。

 #include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=b;i++)
#define Rep(i,a,b) for(int i=(a);i>=b;i--);
#define Formylove return 0
const int N=;
using namespace std;
typedef long long LL;
typedef double db;
int n,m,q,a[N][N],tx[N],vis[N],ti[N];
int nx,ny;
char o[]; template<typename T>void read(T &x) {
char ch=getchar(); T f=; x=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} void walk(int &x,int &y) {
int t1=a[(x+)%n][(y+)%m];
int t2=a[x][(y+)%m];
int t3=a[(x-+n)%n][(y+)%m];
y=(y+)%m;
if(t1>t2&&t1>t3) x=(x+)%n;
else if(t2>t1&&t2>t3) x=x;
else x=(x-+n)%n;
} int mo(int x,int n) { return (x%n+n)%n; } void change(int x,int y) {
x=mo(x,n); y=mo(y,m);
int ex=x,ey=y;
for(;;) {
walk(ex,ey);
if(!ey) break;
}
int l=x,r=x;
while(y) {
if(a[mo(l,n)][mo(y,m)]>a[mo(l-,n)][mo(y,m)]&&a[mo(l,n)][mo(y,m)]>a[mo(l-,n)][mo(y,m)])
l--;
else if(a[mo(l,n)][mo(y,m)]<a[mo(l-,n)][mo(y,m)]&&(l+>r||a[mo(l+,n)][mo(y,m)]<a[mo(l-,n)][mo(y,m)]))
l++;
if(a[mo(r,n)][mo(y,m)]>a[mo(r+,n)][mo(y,m)]&&a[mo(r,n)][mo(y,m)]>a[mo(r+,n)][mo(y,m)])
r++;
else if(a[mo(r,n)][mo(y,m)]<a[mo(r+,n)][mo(y,m)]&&(r-<l||a[mo(r-,n)][mo(y,m)]<a[mo(r+,n)][mo(y,m)])) r--;
if(l>r) break;
y--;
}
if(l>r) return;
if(r-l+>=n) For(i,,n-) tx[i]=ex;
else {
l=mo(l,n); r=mo(r,n);
if(l<=r) For(i,l,r) tx[i]=ex;
else { For(i,,r) tx[i]=ex; For(i,l,n-) tx[i]=ex; }
}
} #define ANS
int main() {
#ifdef ANS
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
#endif
read(n); read(m);
For(i,,n-) For(j,,m-) read(a[i][j]);
For(i,,n-) {
int x=i,y=;
For(j,,m-) walk(x,y);
tx[i]=x;
}
read(q);
nx=,ny=;
while(q--) {
scanf("%s",o);
if(o[]=='m') {
int k;
read(k);
while(k&&ny!=) {
walk(nx,ny);
k--;
}
int tim=;
vis[nx]=q;
ti[nx]=tim;
while(k>=m) {
k-=m;
tim++;
nx=tx[nx];
if(vis[nx]==q) {
int L=tim-ti[nx];
k=k%(L*m);
break;
}
vis[nx]=q;
ti[nx]=tim;
}
while(k>=m) {
nx=tx[nx];
k-=m;
}
while(k) {
walk(nx,ny);
k--;
}
printf("%d %d\n",nx+,ny+);
}
else {
int x,y,z,l,r;
read(x); read(y); read(z);
x--; y--;
a[x][y]=z;
//For(i,0,n-1) printf("%d ",tx[i]); puts("");
change(x,y-);
change(x-,y-);
change(x+,y-);
//For(i,0,n-1) printf("%d ",tx[i]); puts("");
}
}
Formylove;
}

T3优美序列
这题好神啊,我看了很久很久题解和标程也没看懂,去网上搜了一下,看见了其他学校和我们联考的巨佬的博客

第一个巨佬说:这道题可以秒切

第二个巨佬说:这是最简单的一道题

Orz Orz我被这道题和巨佬们秒了。。。什么分治,还什么归并排序的样子,什么st表,全然懵逼

然后我又继续死啃std,根据代码反推出了一个和分治似乎没有半毛钱关系的做法,不知道是std就是这样想的代码和它写的题解并没有联系还是我反推的方式太诡秘,我来口胡一下

把一个优美的序列排序后差分,每一项是1(废话)

那么考虑这样一个判断序列是否优美的方式,如果序列中存在两个数差为1,序列的权值++,如果序列的权值等于序列长度-1,则序列优美。

那么我用线段树维护序列的权值,从左到右扫整个序列,扫到i时线段树上每个叶子节点j表示j到i的序列的权值,这样每加进一个新的数x,只需要看前面有没有x-1,x+1,把1到那个位置区间+1即可。这样扫到i的时候,j~i的序列优美就转换为j的权值=i-j,把j移到左边,就把每个点j权值事先加上j,那么只需要判断权值是否等于现在的i就好了。

这样询问就可以处理了,把询问按右端点从小到大排序,在线段树上维护的同时,扫到一个右端点就把它加进当前询问的set里,set中按左端点从大到小排序。这样在i处理每个询问的时候,就是问1~l的点的权值中最靠右的一个i的位置,因为不优美的区间权值一定是小于i的,线段树只需要维护最靠右的最大值和它的位置就好了。每次查询的时候就是区间查询。如果l较大的查询到的最大值都小于i,那l较小的询问肯定也没有答案,所以set中按左端点排序,时间复杂度十分ok。

 //Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define Formylove return 0
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=;
typedef long long LL;
typedef double db;
using namespace std;
int n,m,a[N],p[N],al[N],ar[N]; template<typename T>void read(T &x) {
char ch=getchar(); x=; T f=;
while(ch!='-'&&(ch<''||ch>'')) ch=getchar();
if(ch=='-') f=-,ch=getchar();
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-''; x*=f;
} struct node {
int l,id;
node(int l,int id):l(l),id(id){}
friend bool operator <(const node&A,const node&B) {
return A.l>B.l||(A.l==B.l&&A.id<B.id);
}
};
vector<node>vc[N]; #define lc (x<<1)
#define rc ((x<<1)|1)
#define mid ((l+r)>>1)
int mx[N<<],pos[N<<],lz[N<<];
void build(int x,int l,int r) {
mx[x]=pos[x]=r;
if(l==r) return;
build(lc,l,mid); build(rc,mid+,r);
} void down(int x,int l,int r) {
if(!lz[x]) return;
mx[lc]+=lz[x]; lz[lc]+=lz[x];
mx[rc]+=lz[x]; lz[rc]+=lz[x];
lz[x]=; return;
} void update(int x,int l,int r,int ql,int qr,int v) {
if(l>=ql&&r<=qr) {
mx[x]+=v; lz[x]+=v; return;
}
down(x,l,r);
if(ql<=mid) update(lc,l,mid,ql,qr,v);
if(qr>mid) update(rc,mid+,r,ql,qr,v);
mx[x]=max(mx[lc],mx[rc]);
pos[x]=(mx[x]==mx[rc]?pos[rc]:pos[lc]);
} #define pr pair<int,int>
#define fi first
#define se second
pr qry(int x,int l,int r,int ql,int qr) {
if(l>=ql&&r<=qr)
return make_pair(mx[x],pos[x]);
down(x,l,r);
if(qr<=mid) return qry(lc,l,mid,ql,qr);
if(ql>mid) return qry(rc,mid+,r,ql,qr);
pr t1=qry(lc,l,mid,ql,qr),t2=qry(rc,mid+,r,ql,qr);
return t2>=t1?t2:t1;
} int find(int l,int r,int id) {
pr t=qry(,,n,,l);
if(t.fi==r) {
al[id]=t.se; ar[id]=r;
return ;
}
return ;
} set<node>s;
void solve() {
build(,,n);
For(i,,n) {
int up=vc[i].size();
For(j,,up-) s.insert(vc[i][j]);
if(a[i]-&&p[a[i]-]<i) update(,,n,,p[a[i]-],);
if(a[i]+<=n&&p[a[i]+]<i) update(,,n,,p[a[i]+],);
while(!s.empty()) {
node t=*s.begin();
if(!find(t.l,i,t.id)) break;
s.erase(s.begin());
}
}
} #define ANS
int main() {
#ifdef ANS
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
#endif
read(n);
For(i,,n) {
read(a[i]);
p[a[i]]=i;
}
read(m);
For(i,,m) {
int l,r;
read(l); read(r);
vc[r].push_back(node(l,i));
}
solve();
For(i,,m) printf("%d %d\n",al[i],ar[i]);
Formylove;
}

NOIp2018集训test-9-15(联考二day1)的更多相关文章

  1. NOIp2018集训test-9-22(am/pm) (联考三day1/day2)

    szzq学长出的题,先orz一下. day1 倾斜的线 做过差不多的题,写在我自己的博客里,我却忘得一干二净,反而李巨记得清清楚楚我写了的. 题目就是要最小化这个东西 $|\frac{y_i-y_j} ...

  2. 六省联考2017 Day1

    目录 2018.3.18 Test T1 BZOJ.4868.[六省联考2017]期末考试 T2 T3 BZOJ.4870.[六省联考2017]组合数问题(DP 矩阵快速幂) 总结 考试代码 T1 T ...

  3. NOIp2018集训test-9-16(联考二day2)

    T1旋转子段 一开始脑袋抽了花了近一个小时写了个跟这题毫无关系的莫名其妙的代码,一急代码就各种bug,最后t1就花了一个半小时多,然后后面时间不太够了,考得稀烂. 因为每个数存在唯一的中心使得绕这个中 ...

  4. NOIp2018集训test-10-6/test-10-7 (联考五day1/day2)

    昨天考完月考,明天初赛,dcoi2017级今天终于开始停课准备noip了,大概没有比本弱校停课更晚的学校了吧.本来就够菜了,怕是要凉透哦. DAY1 T1石头剪刀布 据说爆搜随便做,但是我觉得我的O( ...

  5. NOIp2018集训test-10-4/test-10-5 (联考四day1/day2)

    这个day1稍微有点毒瘤吧?? DAY1 排列 以前总是把day1t1想太复杂了翻车,差不多往正解的方向想了一下感觉不可能这么复杂这可是noipday1t1啊一定有非常简单的方法然后翻车了?? 题目转 ...

  6. NOIp2018集训test-10-21 (联考六day1)

    今天被高一狂踩,两个手抖,t1一个1写成2,t3一个+=写成=,所谓失之毫厘谬以千里,直接丢了50分. 完全背包 看到背包体积如此之大物品体积如此之小容易很想到贪心,肯定要先加很多很多的性价比最高的最 ...

  7. NOIp2018集训test-9-7(pm) (联考一day1)

    又被辉神吊打了.今天不仅被辉神李巨吊打,还给基本上给全班垫底了. 看到T3就知道是十进制快速幂,全机房考试的当时应该就我会,结果我tm没找到递推. Orz lyc BM直接水过,Orz wys六个fo ...

  8. SD六校联考二轮

    数据差评 D1T1 string 直接模拟 每次 string_u = const_string + string_v 理论得分 30 实际可得 100 D2T1 n^2 理论得分 30 实际可得 1 ...

  9. P5290 [十二省联考2019]春节十二响

    题目地址:P5290 [十二省联考2019]春节十二响 骗分方法 如果你实在一点思路也没有,暴力都不会打,那么请考虑一下骗分. 方法一 输出所有 \(M\) 的和. 期望得分:0分. 实际还有5分 方 ...

随机推荐

  1. 获取微信企业的corpID,sercret,access_token,部门设置列表

    获取微信企业的corpID,sercret,access_token,部门设置列表   zabbix调用微信发短信可能用到的一些变量,获取方式如下: 1.corpID(公司ID) 在我的企业--企业信 ...

  2. 【TCP/IP】TCP的三次握手和四次挥手

    传输控制协议(TCP)是一种面向连接的协议,网络程序使用这个协议的时候,网络可以保证客户端和服务端的连接是可靠的,安全的. 如果 A机向 B机发送“hello”,在物理网线上传输的数据不仅仅是“hel ...

  3. Ubuntu下终端命令安装sublime

    Ubuntu下终端命令安装sublime出现软件包无法定位 sublime-text-install 且多次换源不成功 建议采用离线安装 安装教程如下 用Ubuntu上的浏览器下载一个 Sublime ...

  4. PHP ftp_chdir() 函数

    定义和用法 ftp_chdir() 函数改变 FTP 服务器上的当前目录为指定目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE 和一个警告. 语法 ftp_chdir(ftp_co ...

  5. CF 。E2. Stars Drawing (Hard Edition) (DP)

    Description: 定义一个星星由 '*' 组成,形状为一个对称的“十”字型,大小为星星 1/2 的横长(或纵长)减一(如题目中的图).给出一个 n*m 的图,判断是不是每一个 '*' 都能属于 ...

  6. flutter 小知识

    隐藏控件,占空间 new Offstage( offstage: true, //这里控制 child: Container(color: Colors.blue,height: 100.0,), ) ...

  7. Java学习之集合(List接口)

    List特有的常见方法:有一个共性特点:都可以操作角标 1.添加  void add(int index, E element); void addAll(int index, collection& ...

  8. HDU 6695 Welcome Party (贪心)

    2019 杭电多校 10 1005 题目链接:HDU 6695 比赛链接:2019 Multi-University Training Contest 10 Problem Description T ...

  9. The 2019 Asia Nanchang First Round Online Programming Contest(B,E)

    B. Fire-Fighting Hero 题意:一个消防员和多个队伍比赛,比较所有地方的最短路的最大值,消防员最后的值要乘1/C,求胜利的一方的最短路的最大值是多少.一直没读懂正确题意(内疚). 思 ...

  10. 剑指offer——59二叉搜索树的第k大节点

    题目描述 给定一棵二叉搜索树,请找出其中的第k小的结点.例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4.   题解: 考察的就是中序遍历 不过注意进行剪枝 cl ...