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;
}

最后修改:2023 年 07 月 19 日
v我50吃疯狂星期四