loj2537 「PKUWC 2018」Minimax
pkusc 快到了……做点题涨涨 rp。
初见时 yy 了一个类似于归并的东西,\(O(n^2)\),50 分。
50 分 yy 做法
对于一个点,枚举他能到达的权值(假设这个权值在左子树,在右子树是一样的),选上这个点的概率就是“在左子树选上这个点的概率 \(\times\) (选择子结点最大值的概率 \(\times\) 右子树选出比这个点小的点的概率和+选择子结点最小值的概率 \(\times\) 右子树选出比这个点大的点的概率和)”。
100 分
我们发现,瓶颈在于合并。我们先想到启发式合并,然后就不会了。
我们又想到线段树合并。这里就参考ref这里就可以了。
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, uu, num[300005], bb, rot[300005], tot, maxa, maxb, ans;
const int mod=998244353;
struct Node{
int l, r, v;
}nd[300005];
struct SGTNode{
int l, r, v, t;
}sgt[5000005];
int ksm(int a, int b){
int re=1;
while(b){
if(b&1) re = (ll)re * a % mod;
a = (ll)a * a % mod;
b >>= 1;
}
return re;
}
void insert(int &x, int l, int r, int v){
x = ++tot;
sgt[x].v = sgt[x].t = 1;
if(l==r) ;
else{
int mid=(l+r)>>1;
if(v<=mid) insert(sgt[x].l, l, mid, v);
else insert(sgt[x].r, mid+1, r, v);
}
}
void pushDown(int x){
if(!x || sgt[x].t<=1) return ;
sgt[sgt[x].l].t = (ll)sgt[sgt[x].l].t * sgt[x].t % mod;
sgt[sgt[x].r].t = (ll)sgt[sgt[x].r].t * sgt[x].t % mod;
sgt[x].v = (ll)sgt[x].v * sgt[x].t % mod;
sgt[x].t = 1;
}
int merge(int x, int y, int p){
if(!x && !y) return 0;
pushDown(x); pushDown(y);
if(!y){
maxa = (maxa + sgt[x].v) % mod;
sgt[x].t = ((maxb+p)%mod-(ll)2*maxb*p%mod+mod) % mod;
pushDown(x);
return x;
}
if(!x){
maxb = (maxb + sgt[y].v) % mod;
sgt[y].t = ((maxa+p)%mod-(ll)2*maxa*p%mod+mod) % mod;
pushDown(y);
return y;
}
sgt[x].r = merge(sgt[x].r, sgt[y].r, p);
sgt[x].l = merge(sgt[x].l, sgt[y].l, p);
sgt[x].v = (sgt[sgt[x].l].v + sgt[sgt[x].r].v) % mod;
return x;
}
void dfs(int x){
if(!nd[x].l)
insert(rot[x], 1, bb, nd[x].v);
else if(!nd[x].r){
dfs(nd[x].l);
rot[x] = rot[nd[x].l];
}
else{
dfs(nd[x].l);
dfs(nd[x].r);
maxa = maxb = 0;
rot[x] = merge(rot[nd[x].l], rot[nd[x].r], nd[x].v);
}
}
void getAns(int x, int l, int r){
if(!x) return ;
pushDown(x);
if(l==r)
ans = (ans + (ll)l*num[l]%mod*sgt[x].v%mod*sgt[x].v%mod) % mod;
else{
int mid=(l+r)>>1;
getAns(sgt[x].l, l, mid);
getAns(sgt[x].r, mid+1, r);
}
}
int main(){
cin>>n;
for(int i=1; i<=n; i++){
scanf("%d", &uu);
if(nd[uu].l) nd[uu].r = i;
else nd[uu].l = i;
}
int inv=ksm(10000, mod-2);
for(int i=1; i<=n; i++){
scanf("%d", &uu);
if(nd[i].l) nd[i].v = (ll)uu * inv % mod;
else{
nd[i].v = uu;
num[++bb] = uu;
}
}
sort(num+1, num+1+bb);
bb = unique(num+1, num+1+bb) - (num + 1);
for(int i=1; i<=n; i++)
if(!nd[i].l)
nd[i].v = lower_bound(num+1, num+1+bb, nd[i].v) - num;
dfs(1);
getAns(rot[1], 1, bb);
cout<<ans<<endl;
return 0;
}
loj2537 「PKUWC 2018」Minimax的更多相关文章
- LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)
题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(x\) 没有子结点,那么它的权值会在输入 ...
- 「PKUWC 2018」Minimax
传送门:Here 一道线段树合并好题 如果要维护点$ x$的信息,相当于合并$ x$的两棵子树 对于这题显然有:任何叶子节点的权值都可能出现在其祖先上 因而我们只需要在线段树合并的时候维护概率即可 我 ...
- LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)
写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...
- LOJ #2541. 「PKUWC 2018」猎人杀(容斥 , 期望dp , NTT优化)
题意 LOJ #2541. 「PKUWC 2018」猎人杀 题解 一道及其巧妙的题 , 参考了一下这位大佬的博客 ... 令 \(\displaystyle A = \sum_{i=1}^{n} w_ ...
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- loj2538 「PKUWC 2018」Slay the Spire
pkusc 快到了--做点题涨涨 rp. ref我好菜啊QAQ. 可以发现期望只是一个幌子.我们的目的是:对于所有随机的选择方法(一共 \(\binom{2n}{m}\)种),这些选择方法都最优地打出 ...
- loj2540 「PKUWC 2018」随机算法
pkusc 快到了--做点题涨涨 rp. 记 \(f(S,i)\) 表示 \(S\) 这个集合是决计不能选的(要么属于独立集,要么和独立集相连),或称已经考虑了的,\(i\) 表示此集合对应的最大独立 ...
- 「PKUWC 2018」随机算法 (第二版,正解做法)
上一版貌似是打了 O(3 ^ N) 暴力和 一条链的情况,得了60分.... 第一次做的时候光想练一练暴力...就没去想正解,谁知道正解比暴力好写不知道多少,mmp 设 f(S) 为 选集合S中的点可 ...
随机推荐
- iOS核心动画高级技巧之核心动画(三)
iOS核心动画高级技巧之CALayer(一) iOS核心动画高级技巧之图层变换和专用图层(二)iOS核心动画高级技巧之核心动画(三)iOS核心动画高级技巧之性能(四)iOS核心动画高级技巧之动画总结( ...
- Sqlserver计算本年度工作日
--@StartDate 本年度第一天 --@EndDate 本年度最后一天 , ) , DATEADD(yy, , , )) IF EXISTS ( SELECT * FROM tempdb..sy ...
- ubuntu常见错误
ubuntu常见错误--Could not get lock /var/lib/dpkg/lock解决 ubuntu常见错误--Could not get lock /var/lib/dpkg/loc ...
- C++ vector常用法
在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<in ...
- Windows Azure 入门 -- VS 2015部署 ASP.NET网站(项目) 与 数据库
Windows Azure 入门 -- 部署 ASP.NET网站(项目) 与数据库 https://www.dotblogs.com.tw/mis2000lab/2015/12/24/windowsa ...
- 避免使用 JS 特性 with(obj){}
1)简要说明 with 语句可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性.要给对象创建新的属性,必须明确地引用该对象. 2)语法格式 with(object ...
- JSP开发过程遇到的中文乱码问题及解决方案
对于程序猿来说,乱码问题真的很头疼,下面列举几种常见的乱码. 1.数据库编码不一致导致乱码 解决方法: 首先查看数据库编码,输入: show variables like "%char%&q ...
- Java jvm 内存回收机制
http://blog.csdn.net/yaerfeng/article/details/51291903 在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方 ...
- iOS 3DTouch 的开发套路大全
今天休息,先来无事就自己看了一下,关于3d touch,看完后自己有动手尝试了一下,感觉也并不是很难, 经过大量的搜索,目前为止,发现有三种实现方式: 第一种:info文件中添加字段 这种方式,最为直 ...
- Hybrid App开发之css样式使用
前言: 前面学习了html,今天学习一下css的基本使用,看下html与css之间是如何结合来编写前端网页的. CSS 是什么? CSS 是 Cascading Style Sheets(级联样式表) ...