noip34
因为改不动T3而来水博客的屑
昨晚没睡好,大致看了一遍题面后,选择了死亡231,然后就死的很惨。
T1
一开始大致看题面的时候,就略了一眼,加上没读全题,啥思路也没有,最后四十分钟滚回来看了看,发现就是个二分,码好后,发现不太对劲,\(O(n\log n)\) 排序会T,然而不知道该怎么改,就直接交了。
没判0挂了8pts
正解:
就是个二分,二分时间,\(check\) 时计算当前时间各个物品的价值,然后排序,取前m个大,从达到小累加,比 \(s\) 大返回true,否则false。
二分前先判0是否合法,合法直接输出0,不合法再去二分。
然而\(O(n\log n)\) 的 \(sort\) 会T,发现我们只关心前m大的,所以可以用一个叫 \(nth \_element\) 的东西来排序,具体用法:
nth_element(a+head,a+kth,a+tail);
重排 \([head,tail)\) 中的元素,使得 \(kth\) 所指向的元素为拍完序后的该位置出现的数,新的 \(nth\) 元素前所有的元素小于等于新的 \(nth\) 元素后的所有元素。
然后就有个问题,有负的贡献怎么办? 不选不就好了,那它跟0取个 \(\max\) 再排序即可,因为选负的不如不选。
然后就就没了,难点就在于不认识 \(nth\_ element\)
Code
#include<cstdio>
#include<algorithm>
#define MAX 1000100
#define re register
#define int long long
using std::sort;
using std::nth_element;
namespace OMA
{
int n,m,s;
int tmp[MAX];
int ans = 1e9+7;
struct node
{ int k,b; }p[MAX];
struct stream
{
template<typename type>inline stream &operator >>(type &s)
{
int w=1; s=0; 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,*this;
}
}cin;
inline int max(int a,int b)
{ return a>b?a:b; }
inline bool cmp(int a,int b)
{ return a>b; }
inline bool check(int mid)
{
for(re int i=1; i<=n; i++)
{ tmp[i] = max(0,mid*p[i].k+p[i].b); }
//sort(tmp+1,tmp+1+n,cmp);
nth_element(tmp+1,tmp+n-m+1,tmp+n+1);
//for(re int i=1; i<=n; i++)
//{ printf("%lld ",tmp[i]); }
//printf("\n");
int sum = 0;
for(re int i=n; i>=n-m+1; i--)
{
sum += tmp[i];
if(sum>=s)
{ return true; }
}
return false;
}
signed main()
{
//freopen("node.in","r",stdin);
cin >> n >> m >> s;
for(re int i=1,k,b; i<=n; i++)
{ p[i] = (node){(cin >> k,k),(cin>>b,b)}; }
if(check(0))
{ printf("0\n"); return 0; }
int l = 0,r = 1e9;
while(l<=r)
{
int mid = (l+r)>>1;
//printf("l=%d r=%d mid=%d\n",l,r,mid);
if(check(mid))
{ r = mid-1; ans = mid; /*printf("%d %d\n",ans,mid);*/ }
else
{ l = mid+1; }
}
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return OMA::main(); }
记得判0QAQ
T2
一眼看以为高斯消元,看到数据范围直接去世。
短暂的思考发呆犯困之后,选择21pts的特殊性质。
氵完后,试图再搞搞,然而脑子里已经成了浆糊,就滚去T3了。
赛后发现大家都是86pts
正解:
发现对于每个 \(x\) ,都可以表示成 \(x_{i}=k-x_{1}\) 的形式,其中的 \(k\) 是一些 \(w\) 的加加减减,通过手模就可以找到对应的规律,然后就可以方便的回答询问,
- 对于操作1,将表示 \(u,v\) 的式子相加,此时会出现两种情况:
\(x_{u}+x_{v}=t\) ,此时只需判断是否 \(s=t\) ,若相等,则\(inf\),否则 \(none\) 。
\(x_{u}+x_{v}=t\pm x_{1}\) 然后就可以求得 \(x_{1}\) ,注意题目要求 \(x\) 为整数,不符合条件要输出 \(inf\) 。
- 对于操作二,发现对于节点 \(u\) 的修改,实际上只会影响到 \(u\) 的子树内的信息。
所以就是个区间修改+单点查询,修改时根据点深度的奇偶对应的乘上 \(\pm1\) 即可。
所以用个树状数组来实现,复杂度 \(O((n+q)\log n)\)
如果用线段树的话,是两个 \(\log\) 的,过不了最后一个子任务,卡nm呢
然而还是有人用线段树过了
注意判断解不是整数的情况,以及答案最后要除以2。
86pts
#include<cstdio>
#define MAX 1000010
#define re register
namespace OMA
{
int n,q;
int fa[MAX],w[MAX];
int wei[MAX],dep[MAX];
struct graph
{
int next;
int to;
}edge[MAX<<1];
int cnt=1,head[MAX],id[MAX];
inline void add(int u,int v)
{ edge[++cnt] = (graph){head[u],v},head[u] = cnt; }
struct Segment_Tree
{
struct TREE
{
int val;
int l,r;
int lazy;
}st[MAX<<2];
inline int ls(int p)
{ return p<<1; }
inline int rs(int p)
{ return p<<1|1; }
inline void Push_down(int p)
{
if(st[p].lazy)
{
int opt1 = dep[id[st[ls(p)].l]]&1?1:-1;
int opt2 = dep[id[st[rs(p)].l]]&1?1:-1;
st[ls(p)].val += st[p].lazy*opt1;
st[ls(p)].lazy += st[p].lazy;
st[rs(p)].val += st[p].lazy*opt2;
st[rs(p)].lazy += st[p].lazy;
st[p].lazy = 0;
}
}
inline void build(int p,int l,int r)
{
st[p].l = l,st[p].r = r;
if(l==r)
{ st[p].val = wei[id[l]]; 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<=st[p].l&&st[p].r<=r)
{ st[p].val += val*(dep[id[st[p].l]]&1?1:-1),st[p].lazy += 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); }
}
inline int query(int p,int pos)
{
if(st[p].l==st[p].r)
{ return st[p].val; }
Push_down(p);
int ans,mid = (st[p].l+st[p].r)>>1;
if(pos<=mid)
{ return query(ls(p),pos); }
else
{ return query(rs(p),pos); }
}
}Tree;
int dfn[MAX][2];
inline void dfs(int u)
{
dfn[u][0] = ++cnt;
dep[u] = dep[fa[u]]+1;
wei[u] = w[u]-wei[fa[u]];
id[dfn[u][0]] = u;
for(re int i=head[u],v; i; i=edge[i].next)
{ v = edge[i].to; dfs(v); }
dfn[u][1] = cnt;
}
struct stream
{
template<typename type>inline stream &operator >>(type &s)
{
int w=1; s=0; 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,*this;
}
}cin;
signed main()
{
//freopen("node.in","r",stdin);
//freopen("my.out","w",stdout);
cin >> n >> q;
for(re int i=2; i<=n; i++)
{ cin >> fa[i] >> w[i]; add(fa[i],i); }
cnt = 0; dfs(1); Tree.build(1,1,n);
for(re int i=1,opt; i<=q; i++)
{
cin >> opt;
if(opt==1)
{
int u,v,s;
cin >> u >> v >> s;
int opt1 = dep[u]&1,opt2 = dep[v]&1;
int val = Tree.query(1,dfn[u][0])+Tree.query(1,dfn[v][0]);
//printf("val1=%d val2=%d s=%d\n",val1,val2,s);
//printf("%d %d\n",dep[u],dep[v]);
if(opt1==opt2)
{
if((s-val)&1)
{ printf("none\n"); }
else
{ printf("%d\n",(opt1?1:-1)*(s-val)/2); }
}
else
{
if(val==s)
{ printf("inf\n"); }
else
{ printf("none\n"); }
}
}
if(opt==2)
{
int u,val;
cin >> u >> val;
//printf("%d %d\n",dfn[u][0],dfn[u][1]);
if(dep[u]&1)
{ Tree.update(1,dfn[u][0],dfn[u][1],val-w[u]); }
else
{ Tree.update(1,dfn[u][0],dfn[u][1],w[u]-val); }
w[u] = val;
}
}
return 0;
}
}
signed main()
{ return OMA::main(); }
话说我树状数组写错调了好久,要死
100pts
#include<cctype>
#include<cstdio>
#define MAX 1000010
#define re register
#define int long long
namespace OMA
{
int n,q,opt[MAX];
int fa[MAX],w[MAX];
int wei[MAX],dep[MAX];
struct graph
{
int next;
int to;
}edge[MAX];
int cnt=1,head[MAX],id[MAX];
inline void add(int u,int v)
{ edge[++cnt] = (graph){head[u],v},head[u] = cnt; }
struct BIT
{
int tree[MAX];
inline int lowbit(int x)
{ return x&-x; }
inline void update(int x,int y)
{
for(re int i=x; i<=n; i+=lowbit(i))
{ tree[i] += y; }
}
inline void build()
{
for(re int i=1; i<=n; i++)
{ update(i,wei[id[i]]*opt[id[i]]-wei[id[i-1]]*opt[id[i-1]]); }
}
inline int query(int x)
{
int res = 0;
for(re int i=x; i; i-=lowbit(i))
{ res += tree[i]; }
return res*opt[id[x]];
}
}BIT;
int dfn[MAX][2];
inline void dfs(int u)
{
dfn[u][0] = ++cnt;
id[dfn[u][0]] = u;
dep[u] = dep[fa[u]]+1;
wei[u] = w[u]-wei[fa[u]];
for(re int i=head[u],v; i; i=edge[i].next)
{ v = edge[i].to; dfs(v); }
dfn[u][1] = cnt;
}
struct stream
{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
template<typename type>inline stream &operator >>(type &s)
{
int w=0; s=0; char ch=gc();
while(!isdigit(ch)){ w |= ch=='-'; ch=gc(); }
while(isdigit(ch)){ s = (s<<1)+(s<<3)+(ch^48); ch=gc(); }
return s = w?-s:s,*this;
}
}cin;
signed main()
{
cin >> n >> q;
for(re int i=2; i<=n; i++)
{ cin >> fa[i] >> w[i]; add(fa[i],i); }
cnt = 0; dfs(1);
for(re int i=1; i<=n; i++)
{ opt[i] = dep[i]&1?1:-1; }
BIT.build();
for(re int i=1,opt1; i<=q; i++)
{
cin >> opt1;
if(opt1==1)
{
int u,v,s;
cin >> u >> v >> s;
int val = BIT.query(dfn[u][0])+BIT.query(dfn[v][0]);
if(opt[u]==opt[v])
{
if((s-val)&1)
{ printf("none\n"); }
else
{ printf("%lld\n",opt[u]*(s-val)/2); }
}
else
{
if(val==s)
{ printf("inf\n"); }
else
{ printf("none\n"); }
}
}
if(opt1==2)
{
int u,val;
cin >> u >> val;
BIT.update(dfn[u][0],opt[u]*(val-w[u]));
BIT.update(dfn[u][1]+1,-opt[u]*(val-w[u]));
w[u] = val;
}
}
return 0;
}
}
signed main()
{ return OMA::main(); }
T3
考场硬刚,啥也没写出来,暴力也写假,爬了爬了。
正解:
树状数组+扫描线?
不会,咕了
反思总结:
睡好觉....
注意开题顺序,题面读全,不要忽略数据范围。
不要硬刚一道题,时间分配要合理。
noip34的更多相关文章
随机推荐
- bash的RANDOM变量生成的是真正的随机数吗
static void seedrand () { struct timeval tv; gettimeofday (&tv, NULL); sbrand (tv.tv_sec ^ tv.tv ...
- ctf常见编码形式(罗师傅)
https://zhuanlan.zhihu.com/p/30323085 这是原链接 ASCII编码 •ASCII编码大致可以分作三部分组成: •第一部分是:ASCII非打印控制字符(参详ASCII ...
- yoyogo v1.7.5 发布, 独立依赖注入DI
YoyoGo v1.7.5 YoyoGo (Go语言框架) 一个简单.轻量.快速.基于依赖注入的微服务框架( web .grpc ),支持Nacos/Consoul/Etcd/Eureka/k8s / ...
- java基础---java8后新特性
1. java9 新特性 模块化的使用 减少内存的开销. 可简化各种类库和大型应用的开发和维护. 安全性,可维护性,提高性能. 在 module-info.java 文件中,我们可以用新的关键词mod ...
- navicat for sqlserver 注册过程
1.安装原软件,不要打开软件2.将Navicat_Keygen_Patch_v3.4_By_DFoX_URET复制到软件安装位置,运行3.选择navicat v12 products:SQL Serv ...
- Day10 类与对象-面向对象编程(1)
面向对象编程(OOP) 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据. 抽象 三大特征: 封装 继承 多态 从认识论角度考虑是先有对象后有类.对象,是具体的事物.类,是抽象的, ...
- PAT乙级:1053 住房空置率 (20分)
PAT乙级:1053 住房空置率 (20分) 题干 在不打扰居民的前提下,统计住房空置率的一种方法是根据每户用电量的连续变化规律进行判断.判断方法如下: 在观察期内,若存在超过一半的日子用电量低于某给 ...
- PHP如何接收json数据
以前一直在写一些网站,很少涉及到接口的东西.最近公司在做一个平台,需要往接口上发送json数据.闲话少叙,直接上干货. 在php中可以通过如下方式获取: file_get_contents(" ...
- CentOS 7命令行修改网卡名称
在CentOS学习中,配置多个网卡,配置独立的IP地址,为网卡设置新的名称等,已经是必备技能,经小编亲测,以下方法能修改系统的网卡名称,操作步骤和截图一并和小伙伴们分享, 希望对大家的学习和使用有所帮 ...
- GIS数据资源下载
GeoJSON数据下载 1.全国.省.市.县级geojson数据下载 地址:http://datav.aliyun.com/tools/atlas/#&lat=33.5219039961561 ...