noip29
T1
以下的LIS代指最长不降子序列。
考场看到取模,便想到了之前写过的Medain,取模操作让序列分布均匀,对应到本题上,既然是求LIS,那它应该是有循环节的,后来打表证实确实是有。
然后,我码了个BIT优化LIS。觉得应该能拿30pts,然后就傻逼的跳了,其实正解已经想的差不多了,但是本着先把暴力分都拿到的原则,就跳了 我是sb
考场想法:
既然有循环节,那么就只需要把整个序列拆成三部分分别为A,B,C,其中A为包含一个循环节的最短的那一段序列,B全是循环的,C是最后那一段不完全的循环节,如果有的话。
那么就只需要对A求一下LIS,并记录最优答案是从那个位置转移过来的,多个的话全都记,然后看B中有多少个循环节,就对答案产生多少贡献,最后再对记录下来的求一遍LIS,然后对应到C上,看能拿多少。
看似正确,然而我没细想,假了,或者说我的打法假了,比如下面这组数据:
12
134 33 107 69 41
生成序列为:
134 32 16 20 34 35 0 28 32 16 20 34
很显然,LIS长度为5,但我的会输出4,因为它在A中求了个4,选的是 16,20,34,35,导致在C中选不了,但显然,最优应该是在A中选16,20,28,然后在C中32,34,LIS长度为5。
然而考试的时候也没调出来,30pts的也没交上,只能说是活该吧
正解:
就是找循环节,然后一顿乱搞,把循环节接150遍,其他的贡献都是1。
我的那份调了半个下午没调出来,所以换了做法
pdf上的矩阵快速幂不会,也懒的粘了,就这样吧。
Code
#include<cstdio>
#define MAX 1000010
#define re register
namespace OMA
{
long long n,ans;
int t,a,b,c,d,m,len,xam;
int tmp[MAX],pos[MAX];
inline int max(int a,int b)
{ return a>b?a:b; }
class BIT
{
private:
int tree[MAX];
inline int lowbit(int x)
{ return x&-x; }
public:
inline void insert(int x,int lis)
{
for(re int i=x; i<=xam; i+=lowbit(i))
{ tree[i] = max(tree[i],lis); }
}
inline int query(int x)
{
int res = 0;
for(re int i=x; i; i-=lowbit(i))
{ res = max(res,tree[i]); }
return res;
}
}BIT;
signed main()
{
scanf("%lld%d%d%d%d%d",&n,&t,&a,&b,&c,&d);
if(n==1)
{ printf("1\n"); return 0; }
tmp[1] = t;
for(re int i=2; i<=n; i++)
{
xam = max(xam,tmp[i] = (a*tmp[i-1]*tmp[i-1]+b*tmp[i-1]+c)%d);
if(pos[tmp[i]])
{ len = i-pos[tmp[i]],m = i-1; break ; }
pos[tmp[i]] = i;
}
xam += 1;
ans = (n-m)/len-150,n = (n-m)%len+len*150+m;
for(re int i=m+1; i<=n; i++)
{ tmp[i] = tmp[pos[tmp[m+1]]+i-m-1]; }
int lis = 0;
for(re int i=1; i<=n; i++)
{
tmp[i] += 1;
int res = BIT.query(tmp[i])+1;
BIT.insert(tmp[i],res);
lis = max(lis,res);
}
printf("%lld\n",ans+lis);
return 0;
}
}
signed main()
{ return OMA::main(); }
算了,还是贴一下,虽然没有意义
矩阵快速幂解法
T2
一看就不太可做,留在了最后,瞎打了个背包就没看了,然后接着去调T1了。
别人的想法:
同余最短路,能拿90pts,但好像是假的,然而这玩意我都听都没听过,更别提考场写出来
正解:
%%%沈学长。
是个dp,还没写出来,所以先咕了。
dp实质上是在一个图上跑,平常的dp都是有拓扑序,所以可以直接for循环来转移,想这种出现环的,需要跑个最短路来转移。
Code
咕咕咕
T3
考场直接树剖+线段树,然后打着打着发现思路卡壳了,没继续往下想,因为T1自己的想法还没打,所以干脆拿树剖求了个LCA,丢了个暴力就跑回T1了。
正解:
就是个线段树。
首先不难发现,一个节点 \(u\) 的权值,只有可能对自己的子树产生贡献,所以当一个节点 \(u\) 被修改之后,先用 \(u\) 的权值去更新 \(u\) 的子树,然后去暴力跳 \(u\) 的爹 \(fa\) ,那么\(fa\) 的子树中,除去 \(u\) 的子树那一部分都可以用 \(fa\) 的权值去更新,如果 \(fa\) 的子树在修改前就已经有黑点的话,就说明 \(fa\) 的父亲们或者说祖先之前肯定更新过了子树,就不再接着跳了。
说白了就是区间修改+单点查询
Code
#include<cstdio>
#include<cstring>
#include<climits>
#define MAX 100010
#define re register
#define INF INT_MIN
int n,m;
int w[MAX];
bool vis[MAX];
struct graph
{
int next;
int to;
}edge[MAX<<1];
int cnt=1,head[MAX];
inline void add(int u,int v)
{ edge[++cnt] = (graph){head[u],v},head[u] = cnt; }
namespace FTC
{
int fa[MAX],size[MAX],dfn[MAX];
inline void dfs(int u,int fat)
{
size[u] = 1,dfn[u] = ++cnt,fa[u] = fat;
for(re int i=head[u],v; i; i=edge[i].next)
{
v = edge[i].to;
if(v!=fat)
{ dfs(v,u); size[u] += size[v]; }
}
}
}using namespace FTC;
namespace OMA
{
inline int max(int a,int b)
{ return a>b?a:b; }
class Segment_Tree
{
private:
struct TREE
{
int xam;
int l,r;
int tag;
TREE()
{ xam = -1; }
}st[MAX<<2];
inline int ls(int p)
{ return p<<1; }
inline int rs(int p)
{ return p<<1|1; }
inline void Push_up(int p)
{ st[p].xam = max(st[ls(p)].xam,st[rs(p)].xam); }
inline void Push_down(int p)
{
if(st[p].tag)
{
st[ls(p)].xam = max(st[ls(p)].xam,st[p].tag);
st[ls(p)].tag = max(st[ls(p)].tag,st[p].tag);
st[rs(p)].xam = max(st[rs(p)].xam,st[p].tag);
st[rs(p)].tag = max(st[rs(p)].tag,st[p].tag);
st[p].tag = 0;
}
}
public:
inline void build(int p,int l,int r)
{
st[p].l = l,st[p].r = r;
if(l==r)
{ return ; }
int mid = (l+r)>>1;
build(ls(p),l,mid),build(rs(p),mid+1,r);
}
inline void update(int p,int l,int r,int val)
{
if(l>r)
{ return ; }
if(l<=st[p].l&&st[p].r<=r)
{ st[p].xam = max(st[p].xam,val); st[p].tag = max(st[p].tag,val); return ; }
Push_down(p);
int mid = (st[p].l+st[p].r)>>1;
if(l<=mid)
{ update(ls(p),l,r,val); }
if(r>mid)
{ update(rs(p),l,r,val); }
Push_up(p);
}
inline int query(int p,int pos)
{
if(st[p].l==st[p].r)
{ return st[p].xam; }
Push_down(p);
int ans = INF,mid = (st[p].l+st[p].r)>>1;
if(pos<=mid)
{ ans = max(ans,query(ls(p),pos)); }
else
{ ans = max(ans,query(rs(p),pos)); }
return ans;
}
inline void modify(int u)
{
update(1,dfn[u],dfn[u]+size[u]-1,w[u]);
while(!vis[u]&&fa[u])
{
vis[u] = 1;
update(1,dfn[fa[u]],dfn[u]-1,w[fa[u]]);
update(1,dfn[u]+size[u],dfn[fa[u]]+size[fa[u]]-1,w[fa[u]]);
u = fa[u];
}
}
}Tree;
inline int read()
{
int s=0,w=1; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*w;
}
signed main()
{
n = read(),m = read();
for(re int i=1; i<=n; i++)
{ w[i] = read(); }
for(re int i=1,u,v; i<=n-1; i++)
{ u = read(),v = read(); add(u,v),add(v,u); }
cnt = 0,dfs(1,0);
Tree.build(1,1,n);
for(re int i=1,u; i<=m; i++)
{
char s[10]; scanf("%s",s),u = read();
if(s[0]=='M')
{ Tree.modify(u); }
if(s[0]=='Q')
{ printf("%d\n",Tree.query(1,dfn[u])); }
}
return 0;
}
}
signed main()
{ return OMA::main(); }
反思总结:
打暴力不要占用太长时间,不然留给调试可能是正解的代码的时间会不太够,导致出现问题,打完暴力后,也要先把暴力交上,给自己留条后路。
不要去搞极限操作,指在距离考试结束还有7s交代码,rp不好,就会挂掉,是极大概率挂掉。
有想法就要赶快码出来,不要放到最后。
noip29的更多相关文章
- 20210803 noip29
考场 第一次在 hz 考试.害怕会困,但其实还好 看完题感觉不太难,估计有人 AK. T3 比较套路,没办法枚举黑点就从 LCA 处考虑,在一个点变成黑点时计算其他点和它的 LCA 的贡献,暴力跳父亲 ...
随机推荐
- Ubuntu虚拟机基本环境搭建以及参数设置
# 设置root账户密码 sudo passwd root # 修改源镜像(提高下载更新速度) sudo apt-get update pip install open-vm-tools pip in ...
- Linux账号和权限管理(第二回合)
一.组账号文件二.添加组账号groupadd三.添加删除组成员gpasswd四.删除组账号groupdel五.查询账号信息finger六.文件/目录的权限和归属七.设置文件和目录的归属chown 一. ...
- ScienceDirect内容爬虫
爬虫违法,本贴方法只限于个人对数据的分析使用,其爬虫程序已作相关设置,以减小服务器压力.不适宜长期使用. 一.前期准备 1.使用chrome打开ScienceDirect网站(https://www. ...
- 机器学习Sklearn系列:(五)聚类算法
K-means 原理 首先随机选择k个初始点作为质心 1. 对每一个样本点,计算得到距离其最近的质心,将其类别标记为该质心对应的类别 2. 使用归类好的样本点,重新计算K个类别的质心 3. 重复上述过 ...
- python+selenium+unittest发送Mail163邮件(PO)
一.如下为项目的目录分布: 二.数据驱动yaml 三.Mail163登录测试用例编写 四.163邮件配置 五.Mail163测试用例执行: 六.邮件执行情况如下:
- Oracle19c 如何用rman duplicate 克隆一个数据库。(Active方式)
Oracle19c 如何用rman duplicate 克隆一个数据库. 首先克隆有两种方法,一种是Backup-Based,一种是Active方式.官网文档链接https://docs.oracle ...
- vulnhub-DC:1靶机渗透记录
准备工作 在vulnhub官网下载DC:1靶机https://www.vulnhub.com/entry/dc-1,292/ 导入到vmware 打开kali准备进行渗透(ip:192.168.200 ...
- Github上比较全的学习路线
github地址:https://github.com/kamranahmedse/developer-roadmap/blob/master/translations/chinese
- vue3源码难学,先从petite-vue开始吧
如今这个世道,作为一个有几年工作经验的前端,不学点框架源码都感觉要被抛弃了,react或vue要能吹吹牛吧,最好能造个轮子,听说vue3源码好学点,那么学学vue3,但是学起来还是那么费劲,感觉快放弃 ...
- Skywalking-04:扩展Metric监控信息
扩展 Metric 监控信息 官方文档 Source and Scope extension for new metrics 案例:JVM Thread 增加 Metrics 修改 Thread 的定 ...