Codeforces Round #595 (Div. 3)
A. Yet Another Dividing into Teams
手速题
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
int N, a[305], b[305];
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d", &N);
memset(b, 0, sizeof(b));
for(int i=1; i<=N; i++)
{
scanf("%d", &a[i]);
b[a[i]]++;
}
int ans = 1;
for(int i=2; i<=100; i++) ans = max(ans, min(b[i], b[i-1]) + 1);
printf("%d\n", ans);
}
return 0;
}
B. Books Exchange
其实问的就是每个环内的点的个数,岂不是带权并查集维护一下就可以了嘛。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, root[maxN], siz[maxN];
inline int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
inline void init()
{
for(int i=1; i<=N; i++) { root[i] = i; siz[i] = 1; }
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d", &N);
init();
for(int i=1, v; i<=N; i++)
{
scanf("%d", &v);
int fv = fid(v), fu = fid(i);
if(fv != fu)
{
root[fv] = fu;
siz[fu] += siz[fv];
}
}
for(int i=1; i<=N; i++) printf("%d ", siz[fid(i)]);
printf("\n");
}
return 0;
}
C. Good Numbers
一个被的和表示的数是一个good number,但是,每个不能超过一个。那么,我们可以去看二进制的表示,很容易发现,我们可以把一个数那三进制表示,但是有的位可能为2个,这时候就是去给前一位+1,然后对后面的所有直接赋值为0即可。
直接贪心。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
ll x;
int bit[75], top;
inline void solve()
{
top = 0;
while(x)
{
bit[++top] = x % 3;
x /= 3;
}
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%lld", &x);
memset(bit, 0, sizeof(bit));
solve();
if(bit[top] == 2)
{
top++;
bit[top] = 1;
for(int i=top-1; i>=0; i--) bit[i] = 0;
}
else
{
int i, j;
for(i=top-1; i>=1; i--)
{
if(bit[i] == 2)
{
bit[i+1]++;
for(j=i; j>=1; j--) bit[j] = 0;
break;
}
}
for(int k=i+1; k<70; k++)
{
if(bit[k] >= 2)
{
bit[k] = 0; bit[k+1]++;
if(k == top) top++;
}
else break;
}
}
ll ans = 0, tmp = 1LL;
for(int i=1; i<=top; i++)
{
if(bit[i]) ans += bit[i] * tmp;
tmp = tmp * 3LL;
}
printf("%lld\n", ans);
}
return 0;
}
D. Too Many Segments
手玩一下,很容易发现,如果我们对左区间升序,然后去看右区间,这时候会发现,我们应该贪心的选择右端点最远到达的,并且左区间还得包含目前的这个点的,那么我们可以去搜索一下。
现在,D2,N很大,这时候我们肯定得要去优化一下暴力的解法,这里就可以用一下差分来降维了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, K;
struct node
{
int r, id;
node(int b=0, int c=0):r(b), id(c) {}
friend bool operator < (node e1, node e2) { return e1.r < e2.r; }
};
vector<node> add[maxN], del[maxN];
//multiset<node> add[maxN], del[maxN];
multiset<node> now;
multiset<node>::iterator it;
vector<int> vt;
int main()
{
scanf("%d%d", &N, &K);
for(int i=1, l, r; i<=N; i++)
{
scanf("%d%d", &l, &r);
add[l].push_back(node(r, i));
del[r + 1].push_back(node(r, i));
}
for(int i=1; i<=200000; i++)
{
int len = (int)add[i].size();
for(int j=0; j<len; j++) now.insert(add[i][j]);
len = (int)del[i].size();
for(int j=0; j<len; j++) now.erase(del[i][j]);
len = (int)now.size();
if(len > K)
{
int det = len - K;
while(det)
{
it = now.end();
vt.push_back((--it)->id);
now.erase(it);
det--;
}
}
}
int len = (int)vt.size();
printf("%d\n", len);
for(int i=0; i<len; i++) printf("%d ", vt[i]);
printf("\n");
return 0;
}
E. By Elevator or Stairs?
DP,其实最短路也就可以了的。
二维DP,第二维的0表示直接走楼梯,第二维的1表示用了电梯,那么就是需要加上c了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, C;
ll dp[maxN][2], a[maxN], b[maxN];
int main()
{
scanf("%d%d", &N, &C);
memset(dp, INF, sizeof(dp));
dp[1][1] = C;
dp[1][0] = 0;
for(int i=1; i<N; i++) scanf("%lld", &a[i]);
for(int i=1; i<N; i++) scanf("%lld", &b[i]);
for(int i=2; i<=N; i++)
{
dp[i][0] = min(dp[i-1][0], dp[i-1][1]) + a[i-1];
dp[i][1] = min(dp[i-1][0] + C, dp[i-1][1]) + b[i-1];
}
for(int i=1; i<=N; i++) printf("%lld ", min(dp[i][0], dp[i][1]));
printf("\n");
return 0;
}
F. Maximum Weight Subset
树形DP(好像有人用一些什么最大权值的独立集给过了,什么操作啊喂!QAQ?)
题目要找这样的集合,集合内的每个点对相互之间的距离都大于K,并且求其最大的权值。
其实也就是去求最大权值独立集。
怎么搞呢?我们可以去处理每个点的向下的间隔,譬如说,我们的间隔为0,是不是代表了我们把目前的这个点给取了,所以开一个二维dp[ i ][ j ],其中i表示的是结点的序号,j表示的是间隔,于是乎有dp[u][0] = a[u];
画个图吧:
这时候,我们假设K为2,那么如果我取了1这个结点,是不是代表了是一定不可以取2、3两个结点的,然后以此类推。
换个角度来看这个问题,我们现在假如要去取1号点,就代表了dp[1][0] = a[1]; 那么,我们还可以怎样的去表示1这号结点的贡献呢?dp[1][1] = dp[1][1] + max(dp[3][0], dp[7][0]),这个等式可以化简一下,dp[1][1] = dp[1][1] + max(dp[3][0], dp[3][1]),这里,“dp[3][1]”就是等同于“dp[7][0]”,因为代表了不去取3这个结点的a[3],而是改为取7号结点的a[7]。
所以嘛,在这里,如果我们访问到根为u的子树,dp[u][i],以及子结点v,dp[v][j],如果“i + j + 1 > K”就是说明这是我们可以取的结点了,这里的j是需要“+1”的,是因为深度要往上提1了。然后这时候就是去更新答案了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
int N, K, a[205], head[205], cnt, dp[205][205], ans[205];
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[505];
inline void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
void dfs(int u, int fa)
{
dp[u][0] = a[u];
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
dfs(v, u);
memset(ans, 0, sizeof(ans));
for(int x=0; x<=K+1; x++)
{
for(int y=0; y<=K+1; y++)
{
if(x + y >= K)
{
ans[min(x, y + 1)] = max(ans[min(x, y + 1)], dp[u][x] + dp[v][y]);
}
}
}
for(int j=0; j<=K; j++) dp[u][j] = max(dp[u][j], ans[j]);
}
dp[u][0] = max(dp[u][0], dp[u][K + 1] + a[u]);
}
inline void init()
{
for(int i=1; i<=N; i++) head[i] = -1;
cnt = 0;
}
int main()
{
scanf("%d%d", &N, &K);
init();
for(int i=1; i<=N; i++) scanf("%d", &a[i]);
for(int i=1, u, v; i<N; i++)
{
scanf("%d%d", &u, &v);
addEddge(u, v); addEddge(v, u);
}
dfs(1, 0);
int ans = 0;
for(int i=0; i<=K; i++) ans = max(ans, dp[1][i]);
printf("%d\n", ans);
return 0;
}
The End
Rating changes for the last round are temporarily rolled back. They will be returned soon.
难得要涨超级多的分的说,什么时候才给我还回来啊!!!