首页 > 其他分享 >AtCoder Regular Contest 068

AtCoder Regular Contest 068

时间:2022-11-04 16:11:51浏览次数:83  
标签:AtCoder le Contest int 068 i64 Regular maxn 序列

C 简单,D 有点意思,但没啥用,不写。

F 有点好玩,想了一个小时,看了一上午题解,弄明白了。

E - Snuke Line

\(n\) 个物品,第 \(i\) 个物品在 \([l_i,r_i]\) 间。

你初始在第 0 格,要走到第 \(m\) 格,求对于 \(1\sim m\) 每一种步长,走到的格子里的物品种类之和。

\(1\le n\le 10^5,1\le m\le 3\times 10^5\)

很有意思的题目。

首先有一种数论分块的做法,这里略过,可以参考洛谷题解。

这道题树状数组的解法很有参考意义,这里简要说一下:

首先,步长 \(\le r_i-l_i+1\) 的必定含第 \(i\) 种物品,原因显然,而步长 \(\gt r_i-l_i+1\) 只会经过 \([l_i,r_i]\) 至多一次。

离线下来,对于步长 \(x\),将所有 \(r_i-l_i+1\le x\) 的 \([l_i,r_i]\) 区间加,然后调和级数单点查询即可。这样显然不会漏算或多算。最后再加上区间长度大于 \(x\) 的即可。

时间复杂度 \(\mathcal O(n\ln n\log n)\)

Code

// Problem: E - Snuke Line
// Contest: AtCoder - AtCoder Regular Contest 068
// URL: https://atcoder.jp/contests/arc068/tasks/arc068_c
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define fir first
#define sec second
using pii = std::pair<int,int>;

const int maxn = 3e5 + 5;
int c[maxn],n,m;
pii a[maxn];

int lowbit(int x) {
	return x & -x;
}

void add(int x,int y) {
	for(;x <= m;x += lowbit(x))c[x] += y;
	return ;
}

int query(int x) {
	int ans = 0;
	for(;x;x -= lowbit(x))ans += c[x];
	return ans;
}

int main() {
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= n;++ i)
		scanf("%d %d",&a[i].fir,&a[i].sec);
	std::sort(a + 1 , a + 1 + n , [&](const pii& p,const pii& q) {
		return p.sec - p.fir < q.sec - q.fir;
	});
	
	for(int i = 1,j = 1;i <= m;++ i) {
		for(;j <= n&&a[j].sec - a[j].fir + 1 < i;++ j) {
			add(a[j].fir , 1);
			add(a[j].sec + 1 , -1);
		}
		int ans = 0;
		for(int k = i;k <= m;k += i)
			ans += query(k);
		printf("%d\n",ans + n - j + 1);
	}
}

F - Solitaire

给定一个双端队列,将 \(1\sim n\) 从头或尾插入队列。然后再依次从队头或队尾取出元素,形成一个序列,问 1 在序列的第 \(k\) 个位置的序列数量。

\(1\le k\le n\le 2000\)

很神奇的一道题。给出一种 \(\mathcal O(n^2)\) 的算法,似乎有基于 Dilworth 定理的 \(\mathcal O(n)\) 算法,不过我不会,就算了。

首先,根据 ARC F 这类计数题的套路,一开始不要纠结序列的具体形态,尝试思考序列的合法性,找一找序列的性质。

发现这个双端队列中的元素必然呈单谷状,设 \(Q_j=1\),则 \(Q_1\gt Q_2\gt\dots Q_j\lt Q_{j+1}\lt \dots\lt Q_n\)

要让 1 在第 \(k\) 位,就要把 \(Q_{1\sim j-1},Q_{n-(k-j)+1\sim n}\) 先取出来,然后把 \(Q_j\) 取出来。

那么剩下的 \(n-k\) 个数所能构成的序列数为 \(2^{n-k-1}\),我们要关注的是前面一段的数量。

考虑一个长为 \(k\) 的序列怎样才能符合我们的要求:根据双端队列的单谷性质,这个删除序列一定可以划分为两个互不相交的单调递减子序列,分别记为 \(A,B\),并且 \(A,B\) 其中之一的最小值要大于 \(\max\limits_{i\in [j+1,n-(k-j)]}Q_i\)

因为 \(A,B\) 有无序对整个序列无影响,不妨设 \(A\) 的最小值小于 \(B\) 的最小值,且 \(B\) 要满足上述性质(最小值大于那一串式子)

设 \(f(i,j)\) 表示序列中已有 \(i\) 个数,最小值为 \(j\) 时的方案数。

从 \(i-1\to i\) 不好推,我们考虑从 \(i\to i+1\) 这样转移状态。分情况讨论:

  • 新添的数放入 \(A\) 中:设这个数为 \(p\),则 \(p\lt j\),\(f(i,j)\) 转移到 \(f(i+1,p)\)

  • 新添的数放入 \(B\) 中:根据性质,放入的这个数必须是未选数的最大值,不超过 \(n-i\),所以若 \(n-i\lt j\) 就不满足 \(A\) 的最小值比 \(B\) 小的原则,故当 \(j\le n-i\) 时,\(f(i,j)\) 可以转移至 \(f(i+1,j)\)

最后统计下即可。

Code

// Problem: F - Solitaire
// Contest: AtCoder - AtCoder Regular Contest 068
// URL: https://atcoder.jp/contests/arc068/tasks/arc068_d
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using i64 = long long;

const i64 mod = 1e9 + 7;
const int maxn = 2005;
int n,k;
i64 f[maxn][maxn];

i64 power(i64 x,i64 y) {
	i64 ans = 1;
	for(;y;y >>= 1) {
		if(y & 1)(ans *= x) %= mod;
		(x *= x) %= mod;
	}
	return ans;
}

int main() {
	scanf("%d %d",&n,&k);
	if(n <= 2)return printf("1"),0;
	if(k == 1)return printf("%lld\n",power(2 , n - k - 1)),0;
	for(int i = 1;i <= n;++ i)f[1][i] = 1;
	for(int i = 1;i < k - 1;++ i) {
		f[i + 1][n - i + 1] = f[i][n - i + 1];
		for(int j = n - i;j >= 2;-- j)
			(f[i + 1][j] += f[i + 1][j + 1] + f[i][j]) %= mod;
	}
	i64 ans = 0;
	for(int i = 2;i <= n - k + 2;++ i)
		(ans += f[k - 1][i]) %= mod;
	printf("%lld",ans * power(2 , std::max(0 , n - k - 1)) % mod);
	return 0;
}

标签:AtCoder,le,Contest,int,068,i64,Regular,maxn,序列
From: https://www.cnblogs.com/Royaka/p/16858186.html

相关文章

  • Sugoroku 4 (Atcoder abc275 T5) DP
    题目描述题目链接https://atcoder.jp/contests/abc275/tasks/abc275_e题意从\(0\)到\(n\)有\(n+1\)个方格,你现在在第\(0\)个格子。每次移动可以随机走\(1\)......
  • Atcoder Beginner Contest 271(A~G)
    省流:赛时F假了。赛时A转进制;B简单vector。C简单贪心模拟,大概就是能走就走,不能走就先不走(较大)或者存起来(较小),最后走存起来的。挂了3发,自闭了。D第一眼看成了......
  • AtCoder Regular Contest 065
    ARC064C,E都是简单题,D猜结论也没啥意思,就不写了。ARC065还是比较好的。D-Connectivity给定\(n\)个点的无向图,有两组连边,互相独立。询问每个点通过两组连边都......
  • AtCoder Regular Contest 136 D Without Carry
    AtCoder传送门洛谷传送门一眼。将\(a\)中每个数用前导零补到\(6\)位,题目相当于问所有\(i,j\),\(a_i\)的每一位加\(a_j\)的这一位都不超过\(9\)的\((i,j)\)......
  • ATcoder F 做题记录
    ABC273F简要题意一个人要沿数轴从\(0\)处走到\(x\)处,数轴上有一些障碍,每个障碍有一把对应的锤子可以将其销毁,给定障碍和锤子的坐标及\(x\),求最短路长。简要题......
  • Atcoder Beginner Contest 273(A~E+G)
    E场上想麻烦了,调根号分治浪费了点时间;F涉及后缀数组,还没有系统学;G场上没来的及看,也沾点数学,估计场上也想不到(不好,不好。赛时A神笔数组求和;B迷你模拟;C分别找到奇......
  • D - Yet Another Recursive Function -- ATCODER
    D-YetAnotherRecursiveFunctionhttps://atcoder.jp/contests/abc275/tasks/abc275_d 思路动态规划问题。第一印象使用函数递归调用实现,但刚开始担心会爆栈,因为......
  • AtCoder Beginner Contest 275 D~F
    D-YetAnotherRecursiveFunction思路:直觉需要用到的数字大多数是重复的,所以记忆化了一下,测了一下1e18的数据,跑的飞快,直接交了,6ms。#include<bits/stdc++.h>#def......
  • C - Counting Squares -- ATCODER
    C-CountingSquareshttps://atcoder.jp/contests/abc275/tasks/abc275_c参考:https://atcoder.jp/contests/abc275/submissions/36103954 思路首先不能使用暴力穷......
  • 【atcoder 293 F - Erase Subarrays】【动态规划】
    importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;publicclassMain{publicstaticvoidmain(String[]args)......