A - Yet Another Dividing into Teams
因为给出的 n n n个数都是不一样的,所以有两个数相邻答案就是 2 2 2,否则就是 1 1 1。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define esp 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It set<ll>::iterator
#define CLR(x, a) memset(x, a, sizeof(x))
using namespace std;
const ll N = 1e3+5;
ll T, n, m, vis[N];
int main(){
ios::sync_with_stdio(false);
cin>>T;
while (T--){
memset(vis, 0, sizeof(vis));
cin>>n; ll f = 0;
while (n--){
cin>>m; vis[m] = 1;
if (vis[m-1] || vis[m+1]){
f = 1;
}
}
cout<<f+1<<endl;
}
return 0;
}
B1 - Books Exchange (easy version)
n n n最大 200 200 200,模拟走一遍。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define esp 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It set<ll>::iterator
#define CLR(x, a) memset(x, a, sizeof(x))
using namespace std;
const ll N = 1e3+5;
ll T, n, a[N];
int main(){
ios::sync_with_stdio(false);
cin>>T;
while (T--){
cin>>n;
for (ll i = 1; i <= n; i++){
cin>>a[i];
}
for (ll i = 1; i <= n; i++){
ll tmp = a[i], cnt = 1;
while (tmp != i){
tmp = a[tmp]; cnt++;
}
cout<<cnt<<" ";
}
cout<<endl;
}
return 0;
}
B2 - Books Exchange (hard version)
n n n有点大,仔细想一下, n n n个数是一个排列,用并查集把他们分为几个联通块,答案其实就是它所在联通块内点的个数(画个图,每个联通块连成一个圈,瞅一瞅就感觉很有道理)。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define esp 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It set<ll>::iterator
#define CLR(x, a) memset(x, a, sizeof(x))
using namespace std;
const ll N = 2e5+5;
ll T, n, m, f[N], cnt[N];
ll find(ll x){
return f[x] = (f[x]==x ? x : find(f[x]));
}
int main(){
ios::sync_with_stdio(false);
cin>>T;
while (T--){
cin>>n;
for (ll i = 1; i <= n; i++){
f[i] = i; cnt[i] = 1;
}
for (ll i = 1; i <= n; i++){
cin>>m;
ll fu = find(i), fv = find(m);
if (fu != fv){
f[fu] = fv;
cnt[fv] += cnt[fu];
}
}
for (ll i = 1; i <= n; i++){
cout<<cnt[find(i)]<<" ";
}
cout<<endl;
}
return 0;
}
C1 - Good Numbers (easy version)
打个表丢进set,lower_bound直接莽。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define esp 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It set<ll>::iterator
#define CLR(x, a) memset(x, a, sizeof(x))
using namespace std;
const ll N = 2e5+5;
ll T, n;
set<ll> st;
int main(){
ios::sync_with_stdio(false);
ll tmp = 1, sum = 1;
for (ll i = 1; i < 1LL<<15; i++){
ll tmp = i, sum = 0, tt = 1;
while (tmp){
if (tmp & 1){
sum += tt;
}
tt *= 3;
tmp >>= 1;
}
st.insert(sum);
}
cin>>T;
while (T--){
cin>>n;
cout<<*st.lower_bound(n)<<endl;
}
return 0;
}
C2 - Good Numbers (hard version)
{ 1 , 2 , 3 , 4... } \{1, 2, 3, 4...\} {1,2,3,4...}这个序列中的数,如果把它看作二进制的一个状态再把它变成三进制所对应的的数,会发现它是递增的(乱莽)。。。比如 1 1 1和 3 3 3的二进制为 01 01 01和 11 11 11,所对应的三进制数就是 1 = 1 ∗ 3 0 1=1*3^0 1=1∗30和 4 = 1 ∗ 3 1 + 1 ∗ 3 0 4=1*3^1+1*3^0 4=1∗31+1∗30,打个表发现最多到 3 38 3^{38} 338,然后就直接二分, 冲冲冲。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define esp 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It set<ll>::iterator
#define CLR(x, a) memset(x, a, sizeof(x))
using namespace std;
const ll N = 2e5+5;
ll T, n;
int main(){
ios::sync_with_stdio(false);
cin>>T;
while (T--){
cin>>n;
ll l = 1, r = 1LL<<38, ans;
while (l <= r){
ll mid = (l+r)/2, tmp = mid, sum = 0, tt = 1;
while (tmp){
if (tmp & 1){
sum += tt;
}
tt *= 3; tmp >>= 1;
}
if (sum >= n){
ans = sum; r = mid-1;
}
else{
l = mid+1;
}
}
cout<<ans<<endl;
}
return 0;
}
D1 - Too Many Segments (easy version)
反过来想,加入最多的线段数,让点被覆盖的次数小于等于 k k k。
按线段右端点排序,若右端点相同则长度短的优先(肯定是优先考虑短的呗,因为影响的点数越小)。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define eps 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It map<int, int>::iterator
using namespace std;
struct node{
ll l, r, idx;
friend bool operator < (node a, node b){
if (a.r == b.r){
return a.l>b.l;
}
return a.r<b.r;
}
};
const ll N = 2e3+5;
ll n, k, c[N], vis[N];
node line[N];
int main() {
ios::sync_with_stdio(false);
cin>>n>>k;
for (ll i = 1; i <= n; i++){
cin>>line[i].l>>line[i].r; line[i].idx = i;
}
sort(line+1, line+n+1);
ll cnt = 0;
memset(c, 0, sizeof(c));
memset(vis, 0, sizeof(vis));
for (ll i = 1; i <= n; i++){
for (ll j = line[i].l; j <= line[i].r; j++){
c[j]++;
}
ll f = 1;
for (ll j = line[i].l; j <= line[i].r; j++){
if (c[j] > k){
f = 0;
break;
}
}
if (f){
cnt++; vis[line[i].idx] = 1;
}
else{
for (ll j = line[i].l; j <= line[i].r; j++){
c[j]--;
}
}
}
cout<<n-cnt<<endl;
for (ll i = 1; i <= n; i++){
if (!vis[i]){
cout<<i<<" ";
}
}
return 0;
}
D2 - Too Many Segments (hard version)
贪心思路已经找到了,接下来区间变多变长了。
那就用线段树区间查询+更新最大值呗,如果这个线段所在区间的最大值+1小于等于 k k k,则这个区间可取,区间最大值+1。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define eps 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It map<int, int>::iterator
using namespace std;
struct node{
ll l, r, idx;
friend bool operator < (node a, node b){
if (a.r == b.r){
return a.l>b.l;
}
return a.r<b.r;
}
};
struct tree_node{
ll l, r, maxx;
};
const ll N = 2e5+5;
ll n, k, vis[N], lazy[20*N];
node line[N];
tree_node tree[20*N];
void PushUp(ll rt){
tree[rt].maxx = max(tree[rt<<1].maxx, tree[rt<<1|1].maxx);
}
void PushDown(ll rt){
if (lazy[rt]){
lazy[rt<<1] += lazy[rt]; tree[rt<<1].maxx += lazy[rt];
lazy[rt<<1|1] += lazy[rt]; tree[rt<<1|1].maxx += lazy[rt];
lazy[rt] = 0;
}
}
void build(ll l, ll r, ll rt){
tree[rt].l = l; tree[rt].r = r; lazy[rt] = 0;
if (l == r){
tree[rt].maxx = 0;
}
else{
ll mid = (l+r)/2;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
PushUp(rt);
}
}
ll query(ll l, ll r, ll rt){
if (tree[rt].l==l && tree[rt].r==r){
return tree[rt].maxx;
}
else{
PushDown(rt);
ll mid = (tree[rt].l+tree[rt].r)/2;
if (r <= mid){
return query(l, r, rt<<1);
}
else if (l >= mid+1){
return query(l, r, rt<<1|1);
}
else{
return max(query(l, mid, rt<<1), query(mid+1, r, rt<<1|1));
}
}
}
void update(ll l, ll r, ll rt){
if (tree[rt].l==l && tree[rt].r==r){
lazy[rt] += 1; tree[rt].maxx += 1;
return ;
}
if (tree[rt].l != tree[rt].r){
PushDown(rt);
ll mid = (tree[rt].l+tree[rt].r)/2;
if (r <= mid){
update(l, r, rt<<1);
}
else if (l >= mid+1){
update(l, r, rt<<1|1);
}
else{
update(l, mid, rt<<1);
update(mid+1, r, rt<<1|1);
}
PushUp(rt);
}
}
int main() {
ios::sync_with_stdio(false);
cin>>n>>k;
build(1, N, 1);
for (ll i = 1; i <= n; i++){
cin>>line[i].l>>line[i].r; line[i].idx = i;
}
sort(line+1, line+n+1);
ll cnt = 0;
memset(vis, 0, sizeof(vis));
for (ll i = 1; i <= n; i++){
ll tmp = query(line[i].l, line[i].r, 1);
if (tmp+1 <= k){
update(line[i].l, line[i].r, 1);
cnt++; vis[line[i].idx] = 1;
}
}
cout<<n-cnt<<endl;
for (ll i = 1; i <= n; i++){
if (!vis[i]){
cout<<i<<" ";
}
}
return 0;
}
E - By Elevator or Stairs?
d p [ i ] [ 1 ] dp[i][1] dp[i][1]和 d p [ i ] [ 2 ] dp[i][2] dp[i][2]分别代表到第 i i i层走楼梯和坐电梯的最少时间。
d p [ i ] [ 1 ] = m i n ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] ) + a [ i ] dp[i][1] = min(dp[i-1][1], dp[i-1][2])+a[i] dp[i][1]=min(dp[i−1][1],dp[i−1][2])+a[i]
d p [ i ] [ 2 ] = m i n ( d p [ i − 1 ] [ 1 ] + c + b [ i ] , d p [ i − 1 ] [ 2 ] + b [ i ] ) dp[i][2] = min(dp[i-1][1]+c+b[i], dp[i-1][2]+b[i]) dp[i][2]=min(dp[i−1][1]+c+b[i],dp[i−1][2]+b[i])
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define lf double
#define ull unsigned long long
#define eps 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It map<int, int>::iterator
using namespace std;
const ll N = 2e5+5;
ll n, c, a[N], b[N], dp[N][5];
int main() {
ios::sync_with_stdio(false);
cin>>n>>c;
memset(dp, 0, sizeof(dp));
for (ll i = 2; i <= n; i++){
cin>>a[i];
}
for (ll i = 2; i <= n; i++){
cin>>b[i];
}
dp[2][1] = min(dp[1][1], dp[1][2])+a[2];
dp[2][2] = c+b[2];
cout<<0<<" "<<min(dp[2][1], dp[2][2])<<" ";
for (ll i = 3; i <= n; i++){
dp[i][1] = min(dp[i-1][1], dp[i-1][2])+a[i];
dp[i][2] = min(dp[i-1][1]+c+b[i], dp[i-1][2]+b[i]);
cout<<min(dp[i][1], dp[i][2])<<" ";
}
return 0;
}