游记
考前一周
就完全学不太进去文化课了
然后特别想停课但是不行
结果每天翘着作业苟机房,被老师在后面喊打文化课笔记没整呀这样子
Day 0
早上学了一节物理和语文课
(结果考试语文年级 (5001) 名)
接着拿上了东西就出发了
在去德州的大巴上一直和 (An\_Fly) 聊天
到车站面到了 (hzoi2019) 和换了发型的 (skyh)
晚上打了牛客,(orz happyguy) (1A) 下凸包
Day 1
上午学了四毛子算法,颓过了 (Loj6499)
剩下总结下考试吧
关于 (T1)
这次做的比较好的就是没有怵那个大模拟,然后先写了个暴力代码然后算出来了到换历的那些天这样子
这里以后也可以先写个可以帮着算辅助数据和对拍的暴力
其实本质上还是这次暴力写得比较快比较对,也得益于平常训练里面代码能力的提升吧
不过问题就是以后要先考虑测一下大样例再去拍,万一大样例忘记测结果一测挂掉没时间改了那就不成了
关于 (T2)
还是要积累经验和思路吧,二分那个 (Q_i) 没有用是一个,同时还有直接与到一起那样子做
最后的最后: (ull\_ range:[0,2^{64}-1])
如果是减掉一些数的话可以之直接这样写:
(~0ull)-(n-1)
以后考试的时候在简单题目上面不能花费太长时间了,这一下子干掉 (2.5h) 是真的受不了,还得慢慢提升这方面的速度
关于 (T4)
其实考场想到了维护一个最小值,但是不论是写多少分的暴力都没想到可以先记录然后逆序扫,这个确实成了我得到可观分数的一个障碍,这题目收获在这点上了
还有一个就是可以简单写个 (set) 的问题不要写 (splay) ,花时间长,这题目上是一个,还有那个集合论
原来确实没有见过单调队列维护一些信息的,通过贪吃蛇和蚯蚓俩题也积累了一个思路
关于 (T3)
因为是只有 (10min) 写的,没写挂就谢天谢地了
如果再给时间想可能能想到吧,赛时有些细节可能会想不太清楚
大体来看,这次暴力没有打满,就还有不小的提升空间,那么以后就多练练短时间内快速拿高暴力分的能力吧,后俩题的正解就行稳致远了
Solution
儒略日
模拟即可,注意天数太大的要四百年维护一下
写了 (2.5h) 真不知道这题解应该咋写
动物园
直接枚举哪些位已经被占了,这里直接把所有的数字与到一起就行了
注意处理爆 (ull) 的情况
函数调用
发现这个调用肯定是个 (DAG)
按照一些做法就是加法直接跟着后面的乘法做
那么先统计所有序列里面的乘法量,然后拓扑标记和方案
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define reg register
namespace yspm{
inline int read(){
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int mod=998244353,N=1e5+10;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int del(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return x*y-x*y/mod*mod;}
vector<int> g[N];
queue<int> q;
int n,m,a[N],tag[N],v[N],pos[N],num[N],opt[N],in[N],Q,c[N],b[N];
inline void dfs(int x){
if(~tag[x]) return ;
if(opt[x]==1) return tag[x]=1,void();
if(opt[x]==2) return tag[x]=v[x],void();
int siz=g[x].size(); tag[x]=1;
for(reg int i=0;i<siz;++i){
int t=g[x][i]; dfs(t);
tag[x]=mul(tag[x],tag[t]);
}return ;
}
signed main(){
freopen("call.in","r",stdin);
freopen("call.out","w",stdout);
n=read(); for(reg int i=1;i<=n;++i) a[i]=read();
m=read();
for(reg int i=1;i<=m;++i){
opt[i]=read();
if(opt[i]==1) pos[i]=read(),v[i]=read();
if(opt[i]==2) v[i]=read();
if(opt[i]==3){
int x,siz=read();
while(siz--) x=read(),in[x]++,g[i].push_back(x);
}
}
memset(tag,-1,sizeof(tag));
for(reg int i=1;i<=m;++i) dfs(i);
Q=read();
for(reg int i=1;i<=Q;++i) num[i]=read();
int now=1;
for(reg int i=Q;i>=1;--i){
if(opt[num[i]]==1){
b[num[i]]=add(b[num[i]],now);
}else if(opt[num[i]]==2){
now=mul(now,tag[num[i]]);
}else if(opt[num[i]]==3){
b[num[i]]=add(b[num[i]],now);
now=mul(tag[num[i]],now);
}
}
for(reg int i=1;i<=n;++i) a[i]=mul(a[i],now);
for(reg int i=1;i<=m;++i) if(!in[i]) q.push(i);
while(!q.empty()){
int fr=q.front(); q.pop();
if(opt[fr]==2) continue;
if(opt[fr]==1){
a[pos[fr]]=add(a[pos[fr]],mul(v[fr],b[fr]));
continue;
}
int tmp=1,siz=g[fr].size();
for(reg int i=siz-1;i>=0;--i){
int t=g[fr][i];
b[t]=add(b[t],mul(tmp,b[fr]));
tmp=mul(tmp,tag[t]);
--in[t]; if(!in[t]) q.push(t);
}
}
for(reg int i=1;i<=n;++i) printf("%lld ",a[i]); puts("");
return 0;
}
}
signed main(){return yspm::main();}
考后补的
贪吃蛇
考试的是推递归关系没有推清楚
然后 (sb) 一样的 (70 o 20)
现在写篇博客记录一下暴力做法
我们发现这里的最大最小值用 (set) 维护一下
然后把所有的蛇吃的情况模拟出来之后逆序扫一下,如果发现不满足的之际把后面的都置空
那么这样的做法是 (O(Tnlog n)) 的
然后发现后面的扫是不能降复杂度或者得到更好的做法
那么优化前面求最大最小值的部分
以下参考了 (EI) 博客
考虑最大值和最小值的改变
如果 (a_nge 2 a_1) 那么最小值肯定是 (min(a_2,a_n-a_1))
这时候就按照 (NOIP2016) 蚯蚓的套路来进行维护俩单调队列即可
单调性请自行证明
如果 (a_nle 2 a_1) 那么就先将已经维护的两个队列归并一下,这部分可以做到 (O(n))
因为减掉之后(a_n-a_1<a_2) 那么直接成为最小值就行了
不难证明剩下吃的都是小于 (a_2) 的量
如果最后剩下很多值都是(a_1) 但是 (id) 不同,模拟情况即可
因为大模拟写得不少了,就不展开写了
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define reg register
namespace yspm{
inline int read(){
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=1e6+10;
struct node{
int v,id;
bool operator<(const node &a)const{
if(v^a.v) return v<a.v;
return id<a.id;
}
bool operator ==(const node &a)const{return v==a.v&&id==a.id;}
}p[N],q1[N],q2[N],q3[N];
bool fl[N],vis[N];
int pre[N],n,s1[N],s2[N],cnt,a[N],t1,t2,t3,h1,h2,h3;
inline int size2(){return t2-h2+1;}
inline int size1(){return t1-h1+1;}
inline void EI_method(){
memset(vis,0,sizeof(vis));
int mnv=q3[h3].v; vis[q3[h3].id]=1;
int id=1,fp=1; while(fp<=t3&&q3[fp].v==mnv) vis[q3[fp].id]=1,++fp;
while(!vis[id]) ++id; node tmp=(node){-1,-1};
for(reg int i=t3;i>=fp;--i){
s2[++cnt]=q3[i].id;
if(tmp.id!=-1){
s1[cnt]=tmp.id;
if((node){q3[i].v-tmp.v,q3[i].id}<(node){mnv,id}) tmp=(node){q3[i].v-tmp.v,q3[i].id};
else vis[q3[i].id]=1,tmp.id=-1,tmp.v=-1;
}else{
s1[cnt]=id; vis[id]=0;
while(id<=n&&!vis[id]) ++id;
tmp=(node){q3[i].v-mnv,q3[i].id};
}
}
if(tmp.id!=-1&&tmp.v==mnv){
id=tmp.id; tmp.id=-1; tmp.v=-1;
vis[id]=1;
}
if(tmp.id!=-1){
for(reg int i=n;i>=1;--i){
if(vis[i]) s1[++cnt]=tmp.id,s2[cnt]=i,tmp.id=i;
}
}else{
for(reg int i=n,cur=0;i>=1;--i){
if(!vis[i]) continue; cur^=1;
if(cur){
if(tmp.id!=-1) s1[++cnt]=tmp.id,s2[cnt]=i;
tmp.id=i;
}else s1[++cnt]=i,s2[cnt]=tmp.id;
}
}return ;
}
inline void work(){
h1=1; t2=n; h2=n+1; t1=0; cnt=0;
memset(fl,0,sizeof(fl));
for(reg int i=1;i<=n;++i) q1[++t1]=p[i]=(node){a[i],i};
for(reg int i=1;i<=n;++i){
node mx=(node){-1,-1},mn=(node){9e18+10,9e18+10};
if(size1()) mx=max(mx,q1[t1]),mn=min(mn,q1[h1]);
if(size2()) mx=max(mx,q2[t2]),mn=min(mn,q2[h2]);
if(mx.v<mn.v*2){
h3=1; t3=0;
while(size1()&&size2()){
if(q1[h1]<q2[h2]) q3[++t3]=q1[h1++];
else q3[++t3]=q2[h2++];
}
while(size1()) q3[++t3]=q1[h1++];
while(size2()) q3[++t3]=q2[h2++];
EI_method();
break;
}else{
s1[++cnt]=mn.id; s2[cnt]=mx.id;
if(size2()&&mx==q2[t2]) t2--; else t1--;
if(size2()&&mn==q2[h2]) h2++; else h1++;
q2[--h2]=(node){mx.v-mn.v,mx.id};
}
}
int las=n;
for(reg int i=1;i<=n-1;++i) fl[s1[i]]=1;
for(reg int i=n-1;i>=1;--i){
if(fl[s2[i]]){
while(las>i) fl[s1[--las]]=0;
}
}printf("%lld
",n-las+1);
return ;
}
signed main(){
freopen("snakes.in","r",stdin);
freopen("snakes.out","w",stdout);
int T=read(); T--;
n=read(); for(reg int i=1;i<=n;++i) a[i]=read(); work();
while(T--){
int pos,v,siz=read();
while(siz--) pos=read(),v=read(),a[pos]=v;
work();
}
fclose(stdin); fclose(stdout);
return 0;
}
}
signed main(){return yspm::main();}