因为改不动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\) 的式子相加,此时会出现两种情况:
  1. \(x_{u}+x_{v}=t\) ,此时只需判断是否 \(s=t\) ,若相等,则\(inf\),否则 \(none\) 。

  2. \(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

考场硬刚,啥也没写出来,暴力也写假,爬了爬了。

正解:

树状数组+扫描线?

不会,咕了

反思总结:

  1. 睡好觉....

  2. 注意开题顺序,题面读全,不要忽略数据范围。

  3. 不要硬刚一道题,时间分配要合理。

noip34的更多相关文章

随机推荐

  1. JSP核心技术

    一.JSP基本概念 JSP是Java Server Page 的简称,跟Servlet 一样可以动态生成HTML响应,文件命名为XXX.jsp JSP 与Servlet 的区别: jsp经编译后就变成 ...

  2. 何为“Secure Contexts”安全内容? 终于说明白了!

    ​​​何为"Secure Contexts"安全内容? 终于说明白了! 看图说话 [途径1]:地址栏输入: edge://flags/ 按需设置选项后,重启浏览器即可. Allow ...

  3. 实验4 RDD编程初级实践

    1.spark-shell交互式编程 (1) 该系总共有多少学生 scala> val lines = sc.textFile("file:///usr/local/spark/spa ...

  4. java集合(3)-Java8新增的Stream操作集合

    Java8新增了Stream,IntStream,LongStream,DoubleStream等流式API,这些API代表多个支持串行和并行聚集操作的元素.上面的4个接口中,Stream是一个通用的 ...

  5. final修饰符(6)-final类

    final修饰的类不可以有子类,例如:java.lang.Math类就是一个final类,它不可以有子类 子类继承父类,可以访问父类的内部数据,可以重写父类的方法来改变父类方法的实现细节,可能导致不安 ...

  6. Python基础之函数的闭包与装饰器的介绍

    1.闭包的概念: 如果在一个函数中,定义了另外一个函数,并且那个函数使用了外面函数的变量,并且外面那个函数返回了里面这个函数的引用,那么称为里面的这个函数为闭包. 2.话不多说,以demo示例: de ...

  7. 关键字替代符号C++

    不知从什么时候的哪里我看到了一个and关键字,心想这是个什么玩意...然后知道它相当于&&,于是开启了罪恶的生涯-- 替代关键字,似乎可读性更好,但是有些编译器可能会无法识别(eg.M ...

  8. 【洛谷P2041 分裂游戏】数学+瞎蒙

    分析 我们推不出n=3的图,开始猜测,答案在n>2时无解.(<-正解) AC代码 #include <bits/stdc++.h> using namespace std; i ...

  9. 第二十八篇 -- 写一个简陋的WIFI服务器界面

    效果图: Dlg.cpp // WIFIWMITestDlg.cpp : implementation file // #include "stdafx.h" #include & ...

  10. 第七篇 -- photoshop cs6 激活

    下载photoshop cs6破解版 下载amtlib.dll 破解就是将amtlib.dll替换,路径:C:\Program Files\Adobe\Adobe Photoshop CS6 (64 ...