A. 美食诱惑 I
$\tt{z\textcolor{red}{js123}}$
$\tt{z\textcolor{red}{js123}}$
$\tt{z\textcolor{red}{js123}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{c\textcolor{red}{yx2009}}$
Sol
邹锦舒和陈煜轩肯定都会采用贪心策略拿最大的,陈煜轩会拿 $n$,邹锦舒会拿 $n-1$,陈煜轩拿 $n-2$,以此类推。
不难发现,如果把陈煜轩拿一次和邹锦舒拿一次称作一组操作,获得 $1$ 点快乐值。当 $n$ 为偶数时,正好 $\frac{n}{2}$ 次操作。当 $n$ 为奇数时,正好 $\frac{n-1}{2}$ 次操作再拿一个 $1$,获得 $\frac{n+1}{2}$ 快乐值。
利用 C++ 整除下取整的特性,答案为 (n+1)/2
。
注意使用 long long
。
Code
代码
/*
written by : zjs123
QQ : 755328053
Wechat : zoujinshu18
CZOJ : zjs123
luogu : _JSYX_
atcoder : zajasi10
codeforces : _JSYX_
*/
#include<bits/stdc++.h>
using namespace std;
long long n;
main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
cout<<(n+1)/2;
return 0;
}
B. 极速挑战 I
$\tt{z\textcolor{red}{js123}}$
$\tt{z\textcolor{red}{js123}}$
$\tt{z\textcolor{red}{js123}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{J\textcolor{red}{Yawa}}$
Sol
使用 map 映射会很方便。
Code
代码
/*
written by : zjs123
QQ : 755328053
Wechat : zoujinshu18
CZOJ : zjs123
luogu : _JSYX_
atcoder : zajasi10
codeforces : _JSYX_
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
int n,m;
string a[200020];
map<string,int> mm;
int vis[200020];
string x,y;
main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
mm[a[i]]=i;
}
for(int i=1;i<=m;i++){
cin>>x>>y;
int h=(x[0]-'0')*10+x[1]-'0';
int m=(x[3]-'0')*10+x[4]-'0';
if(h>2||h==2&&m>30)continue;
vis[mm[y]]=1;
}
int c=0;
for(int i=1;i<=n;i++){
if(!vis[i]){
cout<<char(c+'A')<<" "<<a[i]<<"\n";
c++;
}
}
return 0;
}
C. 蒸汽时代
$\tt{J\textcolor{red}{Yawa}}$
$\tt{J\textcolor{red}{Yawa}}$
$\tt{J\textcolor{red}{Yawa}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{B\textcolor{red}{yGones}}$
Sol
模拟,贪心。
Code
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[100005][15],c[100005],ans;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=5;j++)
{
char c;
cin>>c;
a[i][j]=c=='x';
}
}
for(int i=1;i<n;i++) cin>>c[i];
int x=n,y=3,p=0;
if(a[x][y])
{
puts("N");
return 0;
}
while(x>1)
{
y=c[--x];
if(a[x][p?6-y:y])
{
p^=1;
ans++;
if(a[x][p?6-y:y])
{
//cout<<x<<' '<<(p?6-y:y)<<endl;
puts("N");
return 0;
}
}
}
cout<<ans;
return 0;
}
D. 棋城要塞
$\tt{w\textcolor{red}{angxiaorui}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{w\textcolor{red}{angxiaorui}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{c\textcolor{red}{yx2009}}$
Sol
最短路。
Code
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 100010;
int Ps, Zs, T;
int n, m, cnt, head[N], dis[N], vis[N], zjh[N], a[N];
struct node
{
int to, next, w;
} edge[M];
struct mtt
{
int k;
bool operator<(const mtt &b) const
{
return dis[b.k] < dis[k];
}
};
void add(int u, int v, int w)
{
edge[++cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
priority_queue<mtt> q;
void Dijkstra()
{
q.push(mtt{Ps});
memset(dis, 0x3f, sizeof(dis));
dis[Ps] = 0;
vis[Ps] = 1;
while (!q.empty())
{
int x = q.top().k;
q.pop();
for (int i = head[x]; i; i = edge[i].next)
{
int y = edge[i].to;
if (dis[y] > dis[x] + edge[i].w)
{
dis[y] = dis[x] + edge[i].w;
if (!vis[y])
q.push(mtt{y});
}
}
}
}
void Work()
{
zjh[Zs] = 0;
int f = 0;
for (int i = 2; i <= T; i++)
{
f = 0;
for (int j = head[a[i - 1]]; j; j = edge[j].next)
if (a[i] == edge[j].to)
{
zjh[a[i]] = max(zjh[a[i]], zjh[a[i - 1]] + edge[j].w);
f = 1;
break;
}
if (!f)
break;
}
}
int main()
{
scanf("%d%d", &n, &m);
int u, v, w;
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
}
scanf("%d", &T);
for (int i = 1; i <= T; i++)
scanf("%d", &a[i]);
scanf("%d%d", &Ps, &Zs);
Dijkstra();
Work();
int ans = 0x3f3f3f3f;
for (int i = 1; i <= T; i++)
if (zjh[a[i]] >= dis[a[i]] && dis[a[i]] != 0x3f3f3f3f)
ans = min(ans, zjh[a[i]]);
if (dis[a[T]] != 0x3f3f3f3f)
ans = min(ans, dis[a[T]]);
if (ans != 0x3f3f3f3f)
printf("%d\n", ans);
else
printf("-1\n");
return 0;
}
E. 美食诱惑 II
$\tt{n\textcolor{red}{ingago}}$
$\tt{n\textcolor{red}{ingago}}$
$\tt{n\textcolor{red}{ingago}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{c\textcolor{red}{yx2009}}$
Sol
很明显的线段树。
码力好的选手可以直接按题意维护。
而我使用的是差分,因此只需要判断最长的正负正负交错的区间就可以。
Code
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 1000010
#define int long long
int n,m;
int a[N],d[N];
struct Tree
{
int l,r,first,last;
int len;
int prelen,suclen;
}tr[N << 2];
#define lson k << 1
#define rson k << 1 | 1
#define Len(x) (tr[x].r - tr[x].l + 1)
int f(int x)
{
if(x < 0)
return -1;
if(x > 0)
return 1;
return 0;
}
void pushup(int k)
{
tr[k].first = tr[lson].first;
tr[k].last = tr[rson].last;
tr[k].len = std::max(tr[lson].len,tr[rson].len);
if(f(tr[lson].last) * f(tr[rson].first) < 0)
tr[k].len = std::max(tr[k].len,tr[lson].suclen + tr[rson].prelen);
tr[k].prelen = tr[lson].prelen;
if(tr[lson].prelen == Len(lson) && f(tr[lson].last) * f(tr[rson].first) < 0)
tr[k].prelen = Len(lson) + tr[rson].prelen;
tr[k].suclen = tr[rson].suclen;
if(tr[rson].suclen == Len(rson) && f(tr[lson].last) * f(tr[rson].first) < 0)
tr[k].suclen = Len(rson) + tr[lson].suclen;
}
void build(int k,int l,int r)
{
tr[k].l = l,tr[k].r = r;
if(l == r)
{
tr[k].first = tr[k].last = d[l];
if(d[l] != 0)
tr[k].len = tr[k].prelen = tr[k].suclen = 1;
else
tr[k].len = tr[k].prelen = tr[k].suclen = 0;
return;
}
int mid = l + r >> 1;
build(lson,l,mid);
build(rson,mid + 1,r);
pushup(k);
}
void change(int k,int q,int z)
{
int l = tr[k].l,r = tr[k].r;
// printf("l : %lld,r : %lld,q = %lld\n",l,r,q);
if(l == r)
{
tr[k].first += z;
tr[k].last += z;
if(tr[k].first != 0)
tr[k].len = tr[k].prelen = tr[k].suclen = 1;
return ;
}
int mid = l + r >> 1;
if(q <= mid)
change(lson,q,z);
else
change(rson,q,z);
pushup(k);
}
void out(int k)
{
// printf("tr[%d to %d].len = %d\n",tr[k].l,tr[k].r,tr[k].len);
if(tr[k].l == tr[k].r)
{
// printf("%d ",tr[k].first);
}
else
{
out(lson);
out(rson);
}
}
signed main()
{
// freopen("maker.in","r",stdin);
// freopen("std.out","w",stdout);
scanf("%lld%lld",&n,&m);
if(!n || !m)
return 0;
for(int i = 1;i <= n;i++)
scanf("%lld",&a[i]);
for(int i = 2;i <= n;i++)
d[i] = a[i] - a[i - 1];
if(n != 1)
build(1,2,n);
for(int i = 1,op,l,r,z;i <= m;i++)
{
scanf("%lld",&op);
if(op == 1)
{
scanf("%lld%lld%lld",&l,&r,&z);
if(l != 1)
change(1,l,z);
if(r != n)
change(1,r + 1,-z);
}
else
{
if(n == 1)
printf("1\n");
else
printf("%lld\n",tr[1].len + 1);
}
// printf("- ");
// out(1);
// putchar('\n');
}
return 0;
}
F. 极速挑战 II
$\tt{J\textcolor{red}{Yawa}}$
$\tt{J\textcolor{red}{Yawa}}$
$\tt{J\textcolor{red}{Yawa}}$
$\tt{c\textcolor{red}{yx2009}}$
$\tt{w\textcolor{red}{angxiaorui}}$
Sol
状压。具体可以查看 UVa1252 Twenty Questions。
Code
代码
// UVa1252 Twenty Questions
// Rujia Liu
#include<bits/stdc++.h>
using namespace std;
const int maxn = 128;
const int maxm = 11;
map<string,int>mp;
int kase, n, m,p;
char objects[maxn][maxm + 100];
int vis[1<<maxm][1<<maxm], d[1<<maxm][1<<maxm];
int cnt[1<<maxm][1<<maxm]; // cnt[s][a]: how many object satisfies: Intersect(featureSet(i), s) = a
// s: the set of features we already asked
// a: subset of s that the object has
int dp(int s, int a) {
if(cnt[s][a] <= 1) return 0;
if(cnt[s][a] == 2) return 1;
int& ans = d[s][a];
if(vis[s][a] == kase) return ans;
vis[s][a] = kase;
ans = m;
for(int k = 0; k < m; k++)
if(!(s & (1<<k))) { // haven't asked
int s2 = s|(1<<k), a2 = a|(1<<k);
if(cnt[s2][a2] >= 1 && cnt[s2][a] >= 1) {
int need = max(dp(s2, a2), // the object has feature k
dp(s2, a)) + 1; // the object doesn't have feature k
ans = min(ans, need);
}
}
return ans;
}
void init() {
for(int s = 0; s < (1<<m); s++) {
for(int a = s; a; a = (a-1)&s)
cnt[s][a] = 0;
cnt[s][0] = 0;
}
for(int i = 0; i < n; i++) {
int features = 0;
for(int f = 0; f < m; f++)
if(objects[i][f] == '1') features |= (1<<f);
for(int s = 0; s < (1<<m); s++)
cnt[s][s & features]++;
}
}
int main() {
cin>>n>>m;
++kase;
for(int i = 0; i < n; i++)
{
int kk;
cin>>kk;
for(int j=0;j<m;j++) objects[i][j]='0';
while(kk--)
{
string s;
cin>>s;
if(!mp[s]) mp[s]=p++;
objects[i][mp[s]]=49;
}
//for(int j=0;j<m;j++) cerr<<objects[i][j]<<' ';cerr<<endl;
}
init();
printf("%d\n", dp(0, 0));
return 0;
}