20210811 Dove 打扑克,Cicada 与排序,Cicada 拿衣服
考场
开考感觉 T3 比较可做。T1 看上去不难但毫无思路。
先想了 25min T3,想到一个确定左端点,二分最长的右端点,甚至想到了用猫树维护区间 or and。。。上厕所回来发现假了,没有单调性
T1 还是不会做,T2 甚至不会写暴力。直到 8.10 才结束思考。
T1 暴力有 80pts,先写了
继续看 T3,根据区间变大后四个变量的变化情况想到了分治,又是想了很久发现复杂度假了,心态就炸了。这时候已经 9.20 了,洗了把脸强行冷静,写了 T3 暴力,但状态很差,写错很多细节。
最后 30min 看 T2,感觉可以枚举 rnd() 的值来算出每种情况下的位置,觉得不太好写在归并排序,预处理了的个数组假装它是随机数。但预处理多长却不好确定。一开始是 \(n\),但样例都过不去,瞎胡分析一波感觉是每个数值的元素个数减一的和,也不太对。最终预处理的 \(21\) 位。
res
rk10 80+15+28
T2 后面的点都 T 了,开到 \(20\) 能多拿 20pts
rk1 熊子豪 100+0+92
rk2 yzf 80+0+100
rk3 肖鸣孜 80+100+0
总结
没啥好说的,就是菜
T1 毕竟没想多久,算是有个借口
T2 又是大 DP,练了这么久还是没啥长进,甚至一点思路都没有。不仅有人场切,而且很多人(比如 ycx)都有思路,只是细节问题/没写完。不擅长不是借口,万一正式比赛考出来怎么办,还是得练。练习的时候多自己想,能抵抗多久题解的诱惑提高就有多少
T3 想了很久都没想到点上,还是性质推的不够,确实也没见过这种做法,但还是很多人想出来了。不仅如此,有人常数小拿了 64pts,有人的乱搞 A 了,也有 72pts 的,但我只拿了最基础的暴力分,对于这种数据有梯度的题就要多卡常、多剪枝,剪枝可以大胆一点。
感觉洗脸挺有用的,起码暴力没挂分。
sol
双没时间写了
T1
const int N = 1e5+5;
int n,m;
int mx,fa[N],val[N],cnt[N];
vector<int> vec;
int find(int x) { return fa[x]==x ? x : fa[x]=find(fa[x]); }
void add(int i)
{ if( !cnt[i]++ ) vec.insert(lower_bound(vec.begin(),vec.end(),i),i); }
void del(int i)
{ if( !--cnt[i] ) vec.erase(remove(vec.begin(),vec.end(),i)); }
signed main() {
read(n,m);
For(i,1,n) fa[i] = i, val[i] = 1, add(1);
while( m-- ) {
int op,x,y; read(op);
if( op == 1 ) {
read(x,y); x = find(x), y = find(y);
if( x == y ) continue;
del(val[x]), del(val[y]);
fa[y] = x, val[x] += val[y];
add(val[x]);
} else {
read(x);
LL ans = 0, suf = 0;
if( !x ) {
for(int i : vec) ans += cnt[i] * (cnt[i]-1ll) / 2;
++x;
}
for(auto it = vec.begin(); it != vec.end(); ++it) suf += cnt[*it];
for(auto itl = vec.begin(), itr = itl; itr != vec.end(); ++itl) {
while( itr != vec.end() && *itr-*itl < x ) suf -= cnt[*itr++];
if( itr == vec.end() ) break;
ans += cnt[*itl] * suf;
}
write(ans);
}
}
return iocl();
}
T2
我写了另一种 DP,时间复杂度也是 \(O(n^3)\),但空间复杂度是 \(O(n^2\log n)\),内存访问不连续,比 sol做法 跑得慢
const int N = 505, mod = 998244353, inv2 = 499122177;
int n,a[N];
LL f[10][N][N],g[N][N];
void merge(int u,int l,int r) {
if( l == r ) return f[u][l][l] = 1, void();
int mid = l+r>>1;
merge(u+1,l,mid), merge(u+1,mid+1,r);
memset(g,0,sizeof g);
g[l][mid+1] = 1;
For(i,l,mid+1) For(j,mid+1,r+1) if( i <= mid || j <= r ) {
g[i][j] %= mod;
if( j == r+1 ) g[i+1][j] += g[i][j];
else if( i == mid+1 ) g[i][j+1] += g[i][j];
else if( a[i] < a[j] ) g[i+1][j] += g[i][j];
else if( a[i] > a[j] ) g[i][j+1] += g[i][j];
else g[i+1][j] += g[i][j] * inv2 %mod, g[i][j+1] += g[i][j] * inv2 %mod;
}
For(i,l,r) For(j,l,mid+1) For(k,mid+1,r+1) if( j <= mid || k <= r ) {
if( k == r+1 ) f[u][i][j+k-mid-1] += f[u+1][i][j] * g[j][k] %mod;
else if( j == mid+1 ) f[u][i][j+k-mid-1] += f[u+1][i][k] * g[j][k] %mod;
else if( a[j] < a[k] ) f[u][i][j+k-mid-1] += f[u+1][i][j] * g[j][k] %mod;
else if( a[j] > a[k] ) f[u][i][j+k-mid-1] += f[u+1][i][k] * g[j][k] %mod;
else f[u][i][j+k-mid-1] += (f[u+1][i][j]+f[u+1][i][k]) * g[j][k] %mod * inv2 %mod;
}
For(i,l,r) For(j,l,r) f[u][i][j] %= mod;
sort(a+l,a+r+1);
}
signed main() {
read(n);
For(i,1,n) read(a[i]);
merge(1,1,n);
For(i,1,n) {
LL ans = 0;
For(j,1,n) ans += f[1][i][j] * j %mod;
write(ans%mod,' ');
}
return iocl();
}
T3
const int N = 1e6+5;
int n,m,a[N];
struct Node { int r,o,an; int val() { return o-an; } };
list<Node> lis;
namespace st {
int lg[N],f[20][N],g[20][N];
void init() {
For(i,2,n) lg[i] = lg[i>>1] + 1;
For(i,1,n) f[0][i] = g[0][i] = a[i];
For(j,1,19) for(int i = 1; i+(1<<j)-1 <= n; ++i)
f[j][i] = max(f[j-1][i],f[j-1][i+(1<<j-1)]),
g[j][i] = min(g[j-1][i],g[j-1][i+(1<<j-1)]);
}
int mx(int l,int r) { int k = lg[r-l+1]; return max(f[k][l],f[k][r-(1<<k)+1]); }
int mn(int l,int r) { int k = lg[r-l+1]; return min(g[k][l],g[k][r-(1<<k)+1]); }
}
namespace seg {
#define ls (u<<1)
#define rs (u<<1|1)
struct Node { int l,r,mx; } t[N*4];
void build(int u,int l,int r) {
t[u].l = l, t[u].r = r, t[u].mx = -1;
if( l == r ) return;
int mid = l+r>>1;
build(ls,l,mid), build(rs,mid+1,r);
}
void modify(int u,int l,int r) {
if( l <= t[u].l && t[u].r <= r ) { ckmax(t[u].mx,r-l+1); return; }
if( l <= t[ls].r ) modify(ls,l,r);
if( t[rs].l <= r ) modify(rs,l,r);
}
void print(int u) {
if( t[u].l == t[u].r ) { write(t[u].mx,' '); return; }
ckmax(t[ls].mx,t[u].mx), ckmax(t[rs].mx,t[u].mx);
print(ls), print(rs);
}
#undef ls
#undef rs
}
bool check(list<Node>::iterator it,int l,int r)
{ return it->val()+st::mn(l,r)-st::mx(l,r) >= m; }
signed main() {
read(n,m);
For(i,1,n) read(a[i]);
st::init(), seg::build(1,1,n);
For(i,1,n) {
for(auto it = lis.begin(); it != lis.end(); ++it)
it->o |= a[i], it->an &= a[i];
lis.pb(Node{i,a[i],a[i]});
for(auto itl = lis.begin(), itr = itl; ++itr != lis.end(); )
if( itl->val() == itr->val() ) lis.erase(itl), itl = itr;
else ++itl;
for(auto it = lis.begin(); it != lis.end(); ++it) if( check(it,it->r,i) ) {
int l = 1, r = it->r;
if( it != lis.begin() ) l = (--it)->r+1, ++it;
while( l < r ) {
int mid = l+r>>1;
if( check(it,mid,i) ) r = mid;
else l = mid+1;
}
seg::modify(1,l,i);
break;
}
}
seg::print(1);
return iocl();
}
20210811 Dove 打扑克,Cicada 与排序,Cicada 拿衣服的更多相关文章
- 「10.28」Dove 打扑克(链表)·Cicada 与排序(概率)·Cicada 拿衣服(各种数据结构)
A. Dove 打扑克 考场思考半天线段树树状数组,没有什么想法 打完暴力后突然想到此题用链表实现会很快. 因为只有$n$堆,所以设最多有$x$个不同的堆数,那么$x\times (x-1)/2==n ...
- [CSP-S模拟测试]:Cicada与排序(概率DP)
题目传送门(内部题93) 输入格式 第一行一个整数$n$,代表数列的长度. 接下来一行$n$个数$a_i$,用空格分隔开. 输出格式 输出一行$n$个数,表示原数列上这个位置在执行后的期望位置,注意输 ...
- NOIP 模拟 $36\; \rm Cicada 与排序$
题解 \(by\;zj\varphi\) 设 \(rk_{i,j}\) 表示第 \(i\) 个数最后在相同的数里排第 \(j\) 位的概率. 转移时用一个 \(dp\),\(dp_{i,j,0/1}\ ...
- [UPC10525]:Dove打扑克(暴力+模拟)
题目描述 $Dove$和$Cicada$是好朋友,他们经常在一起打扑克来消遣时光,但是他们打的扑克有不同的玩法. 最开始时,牌桌上会有$n$个牌堆,每个牌堆有且仅有一张牌,第$i$个牌堆里里里那个扑克 ...
- 晚间测试13 A. Dove 打扑克 vector +模拟
题目描述 分析 这道题比较关键的一点就是要看出最终牌数的种类数不会超过 \(\sqrt{n}\) 种 知道了这个性质我们就可以用 \(vector\) 维护一个有序的序列 \(vector\) 中存放 ...
- NOIP 模拟 $36\; \rm Dove 打扑克$
题解 \(by\;zj\varphi\) 引理 对于一个和为 \(n\) 的数列,不同的数的个数最多为 \(\sqrt n\) 证明: 一个有 \(n\) 个不同的数的数列,和最小就是 \(n\) 的 ...
- 题解 Dove 打扑克
传送门 考场上觉得复杂度是假的就没怎么优化,然后考完题解帮我证明了它是真的-- 首先合并可以用并查集维护,可以顺便维护出集合的大小 对于操作2,发现如果 \(size_i\) 是确定的,可以用权值线段 ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
- csp-s模拟测试91
csp-s模拟测试91 倒悬吃屎的一套题. $T1$认真(?)分析题意发现复杂度不能带$n$(?),计划直接维护答案,考虑操作对答案的影响,未果.突然发现可以动态开点权值线段树打部分分,后来$Tm$一 ...
随机推荐
- netty系列之:netty中的ByteBuf详解
目录 简介 ByteBuf详解 创建一个Buff 随机访问Buff 序列读写 搜索 其他衍生buffer方法 和现有JDK类型的转换 总结 简介 netty中用于进行信息承载和交流的类叫做ByteBu ...
- transform——转换
① 位移 transform:translate(x,y); 同时x轴和y轴的位移 translate(x); 在x轴上的位移 同 translateX(x) translate ...
- 【GCC编译器】Swing Modulo Scheduling
1. SMS 在 GCC 中的实现 1.1. 一些基本概念 (1)软流水(Software pipelining )是一种通过重叠不同迭代的指令,使其并行执行,从而改进循环中指令调度的技术.关键思想是 ...
- ACM金牌选手讲解LeetCode算法《哈希》
大家好,我是编程熊. 往期文章介绍了<线性表>中的数组.链表.栈.队列,以及单调栈和滑动窗口. ACM金牌选手讲解LeetCode算法<线性表> ACM金牌选手讲解LeetCo ...
- linux中的dhcp
目录 一.DHCP服务 二.DHCP的租约过程 三.使用DHCP动态配置主机地址 四.安装DHCP服务器 一.DHCP服务 ① DHCP (Dynamic HostConfiguration Prot ...
- XMAPP搭建DVWA靶机
1 环境搭建 XMAPP+DVWA (我在win10下搭的环境) 更改了xmapp中Apache的两个端口号: dvwa/config中密钥和端口号按自己情况填好: dvwa/config中文件改为 ...
- 计算机专业学了快一年, 只会一点C语言,你好意思说自己是IT专业的?
目录 一.C/C++入门阶段 学习视频推荐:C++入门基础[B站 小甲鱼] 二.C/C++开发进阶 学习视频推荐:C++进阶[慕课网 免费课] 三.C++开发高级 视频教程:程序设计[中国大学MOOC ...
- HashMap底层实现-基础
1.数据结构 1.7 数组+链表,键值对是以Entry内部类的数组存放的.键计算得到哈希值是该数组的下标.又称桶数组当存在哈希冲突时,会通过Entry类内部的成员变量 Entry<k,v> ...
- NOIP 模拟 6 辣鸡
题解 难得啊,本来能 \(AC\) 的一道题,注释没删,挂了五分,难受 此题暴力很好想,就是直接 \(n^2\) 枚举不同的矩阵组合,记录块内答案和跨块的答案 出题人不会告诉你,这题只要输出块内答案就 ...
- Tcp三次握手中细节
TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接,如下图所示.主机A为客户机,主机B为服务器 说明:(1)第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B ...