【AtCoder】AGC012
AGC012
A - AtCoder Group Contest
从最后开始间隔着取就行
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N;
int a[MAXN * 3];
void Solve() {
read(N);
for(int i = 1 ; i <= 3 * N ; ++i) read(a[i]);
sort(a + 1,a + 3 * N + 1);
int64 ans = 0;
for(int i = 3 * N - 1 ; i >= N + 1 ; i -= 2) {
ans += a[i];
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
B - Splatter Painting
大意:有一张图,每个操作是把从v开始距离不超过d的点染成c,求每个点最后的颜色,d<=10
每个点拆成10个,表示从第i个点出发能延伸j长度的询问标号最大的颜色
从后往前处理颜色,遇到不能更新的停止即可
复杂度\(O(dN + M)\)
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int to,next;
}E[MAXN * 2];
int head[MAXN],sumE;
int N,M,Q;
int dp[MAXN][11];
int c[MAXN],d[MAXN],v[MAXN];
void add(int u,int v) {
E[++sumE].to = v;E[sumE].next = head[u];head[u] = sumE;
}
void dfs(int v,int d) {
if(!d) return;
for(int i = head[v] ; i ; i = E[i].next) {
int t = E[i].to;
if(dp[t][d - 1] < dp[v][d]) {
dp[t][d - 1] = dp[v][d];
dfs(t,d - 1);
}
}
}
void Solve() {
read(N);read(M);
int a,b;
for(int i = 1 ; i <= M ; ++i) {
read(a);read(b);
add(a,b);add(b,a);
}
read(Q);
for(int i = 1 ; i <= Q ; ++i) {
read(v[i]);read(d[i]);read(c[i]);
}
for(int i = Q ; i >= 1 ; --i) {
if(dp[v[i]][d[i]] < i) {
dp[v[i]][d[i]] = i;
dfs(v[i],d[i]);
}
}
for(int i = 1 ; i <= N ; ++i) {
int g = 0;
for(int j = 0 ; j <= 10 ; ++j) {
g = max(g,dp[i][j]);
}
out(c[g]);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
C - Tautonym Puzzle
大意:构造一个字符串s长度不超过200,字符集不超过100,要求s的子序列中满足能长度为偶数,前一半字符串和后一半相同的个数正好为N
有点神仙的一道题
就是扔一个1,2,3,4,5,6...N在后面,前面构造一个序列使得最长上升序列为给定值即可
我们发现构造一个最长上升序列时,把最大值扔在前面可以+1,扔在最后可以乘2
那么N只要80左右,总长度是160左右就可以构出来了
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
vector<int> p;
int64 N;
void Solve() {
read(N);
int num = 0,t;
++N;
for(int i = 40 ; i >= 0 ; --i) {
if((N >> i) & 1) {
t = i;
break;
}
}
for(int i = t - 1 ; i >= 0 ; --i) {
++num;
p.pb(num);
if((N >> i) & 1) {
++num;
p.insert(p.begin(),num);
}
}
t = p.size();
for(int i = 1 ; i <= t ; ++i) p.pb(i);
out(p.size());enter;
for(auto a : p) {
out(a);space;
}
enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
D - Colorful Balls
大意:每次选两个相同颜色的球价值总和不超过X,或两个不同颜色的球价值不超过Y,可以交换位置,求不同的颜色序列数
可以把每个点如果能连到同颜色最小点,就和同颜色最小点的并查集连起来
否则如果已经是同颜色最小点或者和同颜色最小点无法连,就和异颜色最小点连起来
只需要处理出价值最小且颜色不同的前两个点即可
之后选出价值最小的那个点的集合(因为若颜色可以交换则一定和它在一个集合)用可重全排列的式子算一下即可
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int fac[MAXN],invfac[MAXN],N,X,Y;
int vp[MAXN],fa[MAXN],id[MAXN];
pii c[MAXN];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void update(int &x,int y) {
x = inc(x,y);
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
int getfa(int x) {
return fa[x] == x ? x : fa[x] = getfa(fa[x]);
}
void Solve() {
read(N);read(X);read(Y);
for(int i = 1 ; i <= N ; ++i) {
read(c[i].se);read(c[i].fi);
}
sort(c + 1,c + N + 1);
int sec = 2;
while(sec <= N && c[sec].se == c[1].se) ++sec;
if(sec > N) {puts("1");return;}
for(int i = N ; i >= 1 ; --i) {
vp[c[i].se] = i;
fa[i] = i;
}
for(int i = N ; i >= 1 ; --i) {
if(i != vp[c[i].se] && c[i].fi + c[vp[c[i].se]].fi <= X) {
fa[getfa(i)] = getfa(vp[c[i].se]);
}
else if(c[i].se != c[1].se && c[i].fi + c[1].fi <= Y) {
fa[getfa(i)] = getfa(1);
}
else if(c[i].se != c[sec].se && c[i].fi + c[sec].fi <= Y) {
fa[getfa(i)] = getfa(sec);
}
}
fac[0] = 1;
for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i);
invfac[N] = fpow(fac[N],MOD - 2);
for(int i = N - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
int siz = 0;
for(int i = 1 ; i <= N ; ++i) {
if(getfa(i) == getfa(1)) {
id[c[i].se]++;
++siz;
}
}
int ans = fac[siz];
for(int i = 1 ; i <= N; ++i) {
ans = mul(ans,invfac[id[i]]);
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
E - Camel and Oases
大意:有n个绿洲排成一排,骆驼能装V的水,最多只能走V的路,或者跳一步到任一点,但是容量变成\(\lfloor \frac{V}{2} \rfloor\),已经储存的水变为0,到了一个绿洲可以吸水,一个绿洲可以吸任意多次的水,问从某个绿洲出发能否遍历所有绿洲
我们显然有\(log V\)种不同的容量,也就是当我们选择了一块区间(这个区间里的点两两距离不超过V,且至多只有logV个区间否则一定impossible)
对于每次容量时,我可以选择这个容量在区间左边用还是右边用,分别是前缀和后缀
于是我们对于前缀dp一个dp[S]表示用了S这个集合的容量,最远可以走遍的前缀是dp[S],后缀同理
于是只需要求出来一个S,\(dpL[S] >= l - 1\)并且\(dpR[All \otimes S] <= r + 1\)即可认为这个区间里的点可以遍历所有绿洲了
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N,V;
int x[MAXN],d[30],tot,r[30][MAXN],l[30][MAXN];
int dp[2][(1 << 19) + 5];
void Solve() {
read(N);read(V);
for(int i = 1 ; i <= N ; ++i) read(x[i]);
d[0] = V / 2;
while(d[tot]) {
++tot;
d[tot] = d[tot - 1] / 2;
}
for(int j = 0 ; j <= tot ; ++j) {
r[j][N] = N;r[j][N + 1] = N + 1;
for(int i = N - 1 ; i >= 1 ; --i) {
r[j][i] = i;
if(x[i + 1] - x[i] <= d[j]) r[j][i] = r[j][i + 1];
}
l[j][1] = 1;
for(int i = 2 ; i <= N ; ++i) {
l[j][i] = i;
if(x[i] - x[i - 1] <= d[j]) l[j][i] = l[j][i - 1];
}
}
dp[0][0] = 0;dp[1][0] = N + 1;
for(int S = 1 ; S < (1 << (tot + 1)) ; ++S) {
dp[1][S] = N + 1;
for(int j = 0 ; j <= tot ; ++j) {
if(S >> j & 1) {
dp[0][S] = max(r[j][dp[0][S ^ (1 << j)] + 1],dp[0][S]);
dp[1][S] = min(l[j][dp[1][S ^ (1 << j)] - 1],dp[1][S]);
}
}
}
int cnt = 0;
for(int i = 1 ; i <= N ; ++i) {
int l = i,r = i;
while(r < N && x[r + 1] - x[r] <= V) ++r;
i = r;
++cnt;
}
if(cnt - 1 > tot + 1) {
for(int i = 1 ; i <= N ; ++i) {
puts("Impossible");
}
return;
}
for(int i = 1 ; i <= N ; ++i) {
int l = i,r = i;
while(r < N && x[r + 1] - x[r] <= V) ++r;
int A = (1 << tot + 1) - 1;
bool f = 0;
for(int S = 0 ; S < (1 << tot + 1) ; ++S) {
if(dp[0][S] >= l - 1 && dp[1][A ^ S] <= r + 1) {f = 1;break;}
}
for(int i = l ; i <= r ; ++i) {
if(f) puts("Possible");
else puts("Impossible");
}
i = r;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
F - Prefix Median
大意:2×N- 1个数,可以重排,每次拿前2×i - 1的中位数作为\(b_{i}\),求不同的\(b_{i}\)的个数
从后往前数,最后一个肯定是全局中位数
事实上我们的选择需要满足第一个数在中间1个,第二个数在中间3个中,第三个数在中间5个中,数可以重复选择
还有要满足的就是不存在\((i < j) B_{j} < B_{i} < B_{j + 1}\)或者\((i < j) B_j > B_{i} > B_{j + 1}\)
这是必要的,可以证明这是充分的
也就是我们对于\(B_{1},B_{2}...B_{n}\)满足这些条件,就一定可以被构造出来
从后往前构造
\(B_{N}\)固定了
我们要选择\(B_{i}\)的时候,如果\(B_{i}\)和\(B_{i + 1}\)一样,我们就删掉左边未出现的数最大的,和右边未出现的数最小的
如果\(B_{i} < B_{i + 1}\)那么我们删掉\(B_1....B_{i - 1}\)中在右边未出现的最小的两个
最后一种情况同理
这样的话也就是已经存在的值域中选左右的两部分,不能选值域非端点的中间
dp状态是\(dp[i][j][k]\)表示从后往前填到第i个数,值域有j个数,当前数是第k个
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N;
int dp[55][105][105];
int a[105],id[MAXN],tot;
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
void update(int &x,int y) {
x = inc(x,y);
}
void Solve() {
read(N);
for(int i = 1 ; i <= 2 * N - 1 ; ++i) read(a[i]);
sort(a + 1,a + 2 * N);
dp[1][1][1] = 1;
for(int i = 1 ; i < N ; ++i) {
for(int j = 1 ; j <= 2 * N - 1 ; ++j) {
for(int h = 1 ; h <= j ; ++h) {
int tj = j,th = h;
if(a[N + i] != a[N + i - 1]) ++tj;
if(a[N - i] != a[N - i + 1]) ++tj,++th;
for(int k = 1 ; k <= tj ; ++k) {
if(k < th)
update(dp[i + 1][k + tj - th + 1][k],dp[i][j][h]);
else if(k > th)
update(dp[i + 1][th + tj - k + 1][th + 1],dp[i][j][h]);
else if(k == th)
update(dp[i + 1][tj][th],dp[i][j][h]);
}
}
}
}
int ans = 0;
for(int j = 1 ; j <= 2 * N - 1 ; ++j) {
for(int h = 1 ; h <= j ; ++h) {
update(ans,dp[N][j][h]);
}
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
【AtCoder】AGC012的更多相关文章
- 【AtCoder】ARC092 D - Two Sequences
[题目]AtCoder Regular Contest 092 D - Two Sequences [题意]给定n个数的数组A和数组B,求所有A[i]+B[j]的异或和(1<=i,j<=n ...
- 【Atcoder】CODE FESTIVAL 2017 qual A D - Four Coloring
[题意]给定h,w,d,要求构造矩阵h*w满足任意两个曼哈顿距离为d的点都不同色,染四色. [算法]结论+矩阵变换 [题解] 曼哈顿距离是一个立着的正方形,不方便处理.d=|xi-xj|+|yi-yj ...
- 【AtCoder】ARC 081 E - Don't Be a Subsequence
[题意]给定长度为n(<=2*10^5)的字符串,求最短的字典序最小的非子序列字符串. http://arc081.contest.atcoder.jp/tasks/arc081_c [算法]字 ...
- 【AtCoder】AGC022 F - Leftmost Ball 计数DP
[题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...
- 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT
[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...
- 【AtCoder】ARC067 F - Yakiniku Restaurants 单调栈+矩阵差分
[题目]F - Yakiniku Restaurants [题意]给定n和m,有n个饭店和m张票,给出Ai表示从饭店i到i+1的距离,给出矩阵B(i,j)表示在第i家饭店使用票j的收益,求任选起点和终 ...
- 【AtCoder】ARC095 E - Symmetric Grid 模拟
[题目]E - Symmetric Grid [题意]给定n*m的小写字母矩阵,求是否能通过若干行互换和列互换使得矩阵中心对称.n,m<=12. [算法]模拟 [题解]首先行列操作独立,如果已确 ...
- 【Atcoder】AGC022 C - Remainder Game 搜索
[题目]C - Remainder Game [题意]给定n个数字的序列A,每次可以选择一个数字k并选择一些数字对k取模,花费2^k的代价.要求最终变成序列B,求最小代价或无解.n<=50,0& ...
- 【Atcoder】AGC 020 B - Ice Rink Game 递推
[题意]n个人进行游戏,每轮只保留最大的a[i]倍数的人,最后一轮过后剩余2人,求最小和最大的n,或-1.n<=10^5. [算法]递推||二分 [题解]令L(i),R(i)表示第i轮过后的最小 ...
随机推荐
- JavaScript中的事件循环
JavaScript是单线程单并发语言 单线程:主程序只有一个线程,即同一时间片段内其只能执行单个任务. 引发的问题: 单线程,意味着任务都需要排队,前一个任务结束,才会执行后一个任务.若前一个任务耗 ...
- FreeBSD--如何最有效率的安装软件
Freebsd 下如何最有效率的安装软件 From <https://www.cnblogs.com/apexchu/p/4131821.html> FreeBSD的默认下载工具是fetc ...
- Centos6.8安装python3.6
1.目的简介: centos默认使用的是python 2.6.6,而python的2.x 和 3.x 是两个不兼容的版本,到目前的python发展,都已经过渡到了python 3.x,所以需要手动将p ...
- PHP Socket服务器搭建和测试
1.socket服务器搭建思路 1) 目的:理解socket服务器工作机制 2) 思路:创建socket -> 把socket加入连接池 -> 处理接收信息 -> 握手动作 -> ...
- 好用的 Html、CSS、JavaScript 开源项目
1.极简模块化前端UI框架 Layui 评分:9.3:收藏量:873 授权协议:MIT 开发语言:JavaScript.HTML/CSS 操作系统:跨平台 源码地址:https://gitee.com ...
- Pandas 索引和切片
Series和Datafram索引的原理一样,我们以Dataframe的索引为主来学习 列索引:df['列名'] (Series不存在列索引) 行索引:df.loc[].df.iloc[] 选择列 / ...
- SVN 的基本用法
克隆远程库 # svn checkout $URL --username=$userName 显示库信息 # svn info 显示库状态 # svn status 将文件纳入版本管理 # svn a ...
- [bzoj3371][poj2009][Usaco2004 Mar]Moo University - Emergency Pizza Order 定制比萨饼
标题这么长的..真是让感觉人头大脚轻. 贴题面先. Description Moo大学的餐厅必须为$C(1\leq C\leq 1000)$头入学的奶牛新生定制比萨饼.比萨饼可以在比萨小屋订做 ...
- laravel5.5路由使用name的好处
使用name的好处 辅助函数 route 可以用于为指定路由生成 URL.命名路由生成的 URL 不与路由上定义的 URL 相耦合.因此,就算路由的 URL 有任何更改,都不需要对 route 函数调 ...
- 内存压缩PK页面交换 解决内存问题谁更在行
一台服务器能够支持的虚拟机数量通常取决于物理硬件所能够提供的可用计算资源.大多数资源, 比如处理器周期.存储I/O和网络带宽等,都能够相对简单地进行共享.这种做法的原理在于负载并不总是处于忙碌状态,因 ...