牛客网暑期ACM多校训练营(第二场)A run D money H travel I car J farm

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lfhase/article/details/81157619

比赛(题目)链接:https://www.nowcoder.com/acm/contest/140#question

A

签到题,每个点只会影响后面1步和k步的点,注意不要重复两次k就好了

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
 
using namespace std;
 
const int MAXN = 100005;
const int MOD = 1e9+7;
 
long long DP_1[MAXN];
long long DP_2[MAXN];
long long DP[MAXN];
long long STEP;
 
 
int main()
{
    int Q;
    while(scanf("%d%lld",&Q,&STEP)!=EOF)
    {
        memset(DP_1,0,sizeof(DP_1));
        memset(DP_2,0,sizeof(DP_2));
        //for(int i=1;i<MAXN;++i)    DP[i] = 1;
        DP_1[0] = 1;
        for(int i=0;i<MAXN;++i)
        {
            if(i+STEP<MAXN)
            {
                DP_2[STEP+i] = (DP_2[STEP+i]+DP_1[i])%MOD;
            }
            if(i+1<MAXN)
            {
                DP_1[i+1] = (DP_1[i+1]+DP_1[i]+DP_2[i])%MOD;
            }
        }
 
       /* for(int i=1;i<MAXN;++i)
            cout<<(DP_1[i]+DP_2[i])<<" ";
        cout<<endl;*/
        DP[0] = 0;
        for(int i=1;i<MAXN;++i)
        {
            DP[i] = (DP[i-1]+DP_1[i]+DP_2[i])%MOD;
            /*if(i<=100)
            cout<<DP[i]<<" ";*/
        }
 
 
        while(Q--)
        {
            long long res = 0;
            int l, r;
            scanf("%d%d",&l,&r);
            res = (DP[r]-DP[l-1])%MOD;
            if(res<0)   res+=MOD;
            printf("%lld\n",res);
        }
    }
    return 0;
}

D

签到题,贪心地取所有递增连续子序列最后两值相减即可。

AC代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
 
using namespace std;
 
const int MAXN = 100005;
const int MOD = 1e9+7;
 
int N;
 
 
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>N;
        long long profit = 0;
        long long times = 0;
        long long cur = -1;
        long long curnum;
        long long lastnum=-1;
        for(int i=1;i<=N;++i)
        {
            scanf("%lld",&curnum);
            if((lastnum!=-1&&cur==-1&&lastnum<curnum))
            {
                cur = lastnum;
            }
            else if(lastnum!=-1&&cur!=-1&&curnum<lastnum)
            {
                profit += lastnum-cur;
                times+=2;
                cur = -1;
            }
            lastnum = curnum;
        }
        if(cur!=-1&&lastnum>cur)    profit+=lastnum-cur, times+=2;
        printf("%lld %lld\n",profit,times);
    }
    return 0;
}

树形DP

设置两个数组:

DP [ i, j ] :表示树上前i个点选择j条链的最大值

SLink [ i, j ] : 表示树上前i个点选择j条链和一条包含i的直链(i为端点到叶子)的最大值

对于每一个子树,它对结果的贡献可以是:

1) None;

2)1,2,3条路径;

3) 一条直链+0,1,2,3条路径;

合并时按上述情况分类讨论即可,注意在存在直链的子树合并时,需要减1。

AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 400005;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int N;
int weight[MAXN];
vector<int> mapp[MAXN];

long long DP[MAXN][5];
long long SLink[MAXN][5];

void rua(int u, int fa=0)
{
    long long maxn[5][5], curmaxn[5][5], submaxn[5][5];
    memset(maxn,0,sizeof(maxn));
    memset(curmaxn,0,sizeof(curmaxn));
    memset(submaxn,0,sizeof(submaxn));
    for(int e:mapp[u])
    {
        if(e!=fa)
        {
            rua(e,u);
            for(int i=0;i<=3;++i)   submaxn[i][0]=DP[e][i], submaxn[i][1]=SLink[e][i];
            for(int x1=0;x1<=3;++x1)
                for(int x2=0;x2+x1<=3;++x2)
                    for(int sy1=0;sy1<=2;++sy1)
                        for(int sy2=0;sy2+sy1<=3;++sy2)
                            maxn[x1+x2][sy1+sy2] = max(maxn[x1+x2][sy1+sy2],curmaxn[x1][sy1]+submaxn[x2][sy2]);
            memcpy(curmaxn,maxn,sizeof(maxn));
        }
    }
    for(int i=0;i<=3;++i)   DP[u][i] = max(DP[u][i],maxn[i][0]);
    for(int i=1;i<=3;++i)   DP[u][i] = max(DP[u][i],maxn[i-1][1]+weight[u]);
    for(int i=1;i<=3;++i)   DP[u][i] = max(DP[u][i],maxn[i-1][2]+weight[u]);
    for(int i=0;i<=3;++i)   SLink[u][i] = max(SLink[u][i],maxn[i][1]+weight[u]);
}



int main()
{
    //freopen("output.txt","w+",stdout);
    int u, v;
    scanf("%d",&N);
    for(int i=1;i<=N;++i)   scanf("%d",weight+i);
    for(int i=1;i<N;++i)
    {
        scanf("%d%d",&u,&v);
        mapp[u].push_back(v);
        mapp[v].push_back(u);
    }

    rua(1,0);
    printf("%lld",DP[1][3]);

    return 0;
}

I

找规律?规律就是n为偶数时能通过的车为2n,n为奇数时能通过的车是2n-1

摧毁格子时对应行列减一,注意奇数情况下对中心行列的处理即可。

AC代码如下:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;

const int MAXN = 100005;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int N, M;
int cordx[MAXN], cordy[MAXN];


int main()
{
    //freopen("output.txt","w+",stdout);
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        int res = N*2-(N%2);
        memset(cordx,0,sizeof(cordx));
        memset(cordy,0,sizeof(cordy));
        int x, y;

        /* for(int i=1;i<=N;++i)
             cout<<cordx[i]<<" ";
         cout<<endl;
         for(int j=1;j<=N;++j)
             cout<<cordy[j]<<" ";
         cout<<endl;*/
        for(int i=1; i<=M; ++i)
        {
            scanf("%d%d",&x,&y);

            if(!cordx[x])
            {
                res --;
                cordx[x] = 1;
            }
            if(!cordy[y])
            {
                res--;
                cordy[y] = 1;
            }

        }
        if(cordx[(N+1)/2]==cordy[(N+1)/2]&&cordy[(N+1)/2]==1)   res++;
        /*for(int i=1;i<=N;++i)
            cout<<cordx[i]<<" ";
        cout<<endl;
        for(int j=1;j<=N;++j)
            cout<<cordy[j]<<" ";
        cout<<endl;*/

        printf("%d\n",res);
    }
    return 0;
}

J

二维树状数组

考虑到每种肥料只会对对应种类的植物有作用,所以按植物/肥料种类进行分类判断

对每种植物,对农场矩阵施加非该种植物的化肥,

然后对该种植物每个点做一次前缀和判断,如果是0则无影响,如果是1则有影响。

AC代码如下:(事实上不用IO加速也能过【tao

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define R register

namespace fastIO {
#define BUF_SIZE 100005
#define OUT_SIZE 100005
#define ll long long
  //fread->read
  bool IOerror = 0;
  inline char nc() {
    static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
    if (p1 == pend) {
      p1 = buf;
      pend = buf + fread(buf, 1, BUF_SIZE, stdin);
      if (pend == p1) {
    IOerror = 1;
    return -1;
      }
      //{printf("IO error!\n");system("pause");for (;;);exit(0);}
    }
    return *p1++;
  }
  inline bool blank(char ch) {
    return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
  }
  inline void read(int &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc());
    if (IOerror)return;
    if (ch == '-')sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
    if (sign)x = -x;
  }
  inline void read(ll &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc());
    if (IOerror)return;
    if (ch == '-')sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
    if (sign)x = -x;
  }
  inline void read(double &x) {
    bool sign = 0;
    char ch = nc();
    x = 0;
    for (; blank(ch); ch = nc());
    if (IOerror)return;
    if (ch == '-')sign = 1, ch = nc();
    for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
    if (ch == '.') {
      double tmp = 1;
      ch = nc();
      for (; ch >= '0' && ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0');
    }
    if (sign)x = -x;
  }
  inline void read(char *s) {
    char ch = nc();
    for (; blank(ch); ch = nc());
    if (IOerror)return;
    for (; !blank(ch) && !IOerror; ch = nc()) * s++ = ch;
    *s = 0;
  }
  inline void read(char &c) {
    for (c = nc(); blank(c); c = nc());
    if (IOerror) {
      c = -1;
      return;
    }
  }
  //getchar->read
  inline void read1(int &x) {
    char ch;
    int bo = 0;
    x = 0;
    for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar())if (ch == '-')bo = 1;
    for (; ch >= '0' && ch <= '9'; x = x * 10 + ch - '0', ch = getchar());
    if (bo)x = -x;
  }
  inline void read1(ll &x) {
    char ch;
    int bo = 0;
    x = 0;
    for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar())if (ch == '-')bo = 1;
    for (; ch >= '0' && ch <= '9'; x = x * 10 + ch - '0', ch = getchar());
    if (bo)x = -x;
  }
  inline void read1(double &x) {
    char ch;
    int bo = 0;
    x = 0;
    for (ch = getchar(); ch < '0' || ch > '9'; ch = getchar())if (ch == '-')bo = 1;
    for (; ch >= '0' && ch <= '9'; x = x * 10 + ch - '0', ch = getchar());
    if (ch == '.') {
      double tmp = 1;
      for (ch = getchar(); ch >= '0' && ch <= '9'; tmp /= 10.0, x += tmp * (ch - '0'), ch = getchar());
    }
    if (bo)x = -x;
  }
  inline void read1(char *s) {
    char ch = getchar();
    for (; blank(ch); ch = getchar());
    for (; !blank(ch); ch = getchar()) * s++ = ch;
    *s = 0;
  }
  inline void read1(char &c) {
    for (c = getchar(); blank(c); c = getchar());
  }
  //scanf->read
  inline void read2(int &x) {
    scanf("%d", &x);
  }
  inline void read2(ll &x) {
#ifdef _WIN32
    scanf("%I64d", &x);
#else
#ifdef __linux
    scanf("%lld", &x);
#else
    puts("error:can recognize the system!");
#endif
#endif
  }
  //fwrite->write
  struct Ostream_fwrite {
    char *buf, *p1, *pend;
    Ostream_fwrite() {
      buf = new char[BUF_SIZE];
      p1 = buf;
      pend = buf + BUF_SIZE;
    }
    void out(char ch) {
      if (p1 == pend) {
    fwrite(buf, 1, BUF_SIZE, stdout);
    p1 = buf;
      }
      *p1++ = ch;
    }
    void print(int x) {
      static char s[15], *s1;
      s1 = s;
      if (!x)*s1++ = '0';
      if (x < 0)out('-'), x = -x;
      while(x)*s1++ = x % 10 + '0', x /= 10;
      while(s1-- != s)out(*s1);
    }
    void println(int x) {
      static char s[15], *s1;
      s1 = s;
      if (!x)*s1++ = '0';
      if (x < 0)out('-'), x = -x;
      while(x)*s1++ = x % 10 + '0', x /= 10;
      while(s1-- != s)out(*s1);
      out('\n');
    }
    void print(ll x) {
      static char s[25], *s1;
      s1 = s;
      if (!x)*s1++ = '0';
      if (x < 0)out('-'), x = -x;
      while(x)*s1++ = x % 10 + '0', x /= 10;
      while(s1-- != s)out(*s1);
    }
    void println(ll x) {
      static char s[25], *s1;
      s1 = s;
      if (!x)*s1++ = '0';
      if (x < 0)out('-'), x = -x;
      while(x)*s1++ = x % 10 + '0', x /= 10;
      while(s1-- != s)out(*s1);
      out('\n');
    }
    void print(double x, int y) {
      static ll mul[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
            1000000000, 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL,
            100000000000000LL, 1000000000000000LL, 10000000000000000LL, 100000000000000000LL
      };
      if (x < -1e-12)out('-'), x = -x;
      x *= mul[y];
      ll x1 = (ll)floor(x);
      if (x - floor(x) >= 0.5)++x1;
      ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y];
      print(x2);
      if (y > 0) {
    out('.');
    for (size_t i = 1; i < y && x3 * mul[i] < mul[y]; out('0'), ++i);
    print(x3);
      }
    }
    void println(double x, int y) {
      print(x, y);
      out('\n');
    }
    void print(char *s) {
      while (*s)out(*s++);
    }
    void println(char *s) {
      while (*s)out(*s++);
      out('\n');
    }
    void flush() {
      if (p1 != buf) {
    fwrite(buf, 1, p1 - buf, stdout);
    p1 = buf;
      }
    }
    ~Ostream_fwrite() {
      flush();
    }
  } Ostream;
  inline void print(int x) {
    Ostream.print(x);
  }
  inline void println(int x) {
    Ostream.println(x);
  }
  inline void print(char x) {
    Ostream.out(x);
  }
  inline void println(char x) {
    Ostream.out(x);
    Ostream.out('\n');
  }
  inline void print(ll x) {
    Ostream.print(x);
  }
  inline void println(ll x) {
    Ostream.println(x);
  }
  inline void print(double x, int y) {
    Ostream.print(x, y);
  }
  inline void println(double x, int y) {
    Ostream.println(x, y);
  }
  inline void print(char *s) {
    Ostream.print(s);
  }
  inline void println(char *s) {
    Ostream.println(s);
  }
  inline void println() {
    Ostream.out('\n');
  }
  inline void flush() {
    Ostream.flush();
  }
  //puts->write
  char Out[OUT_SIZE], *o = Out;
  inline void print1(int x) {
    static char buf[15];
    char *p1 = buf;
    if (!x)*p1++ = '0';
    if (x < 0)*o++ = '-', x = -x;
    while(x)*p1++ = x % 10 + '0', x /= 10;
    while(p1-- != buf)*o++ = *p1;
  }
  inline void println1(int x) {
    print1(x);
    *o++ = '\n';
  }
  inline void print1(ll x) {
    static char buf[25];
    char *p1 = buf;
    if (!x)*p1++ = '0';
    if (x < 0)*o++ = '-', x = -x;
    while(x)*p1++ = x % 10 + '0', x /= 10;
    while(p1-- != buf)*o++ = *p1;
  }
  inline void println1(ll x) {
    print1(x);
    *o++ = '\n';
  }
  inline void print1(char c) {
    *o++ = c;
  }
  inline void println1(char c) {
    *o++ = c;
    *o++ = '\n';
  }
  inline void print1(char *s) {
    while (*s)*o++ = *s++;
  }
  inline void println1(char *s) {
    print1(s);
    *o++ = '\n';
  }
  inline void println1() {
    *o++ = '\n';
  }
  inline void flush1() {
    if (o != Out) {
      if (*(o - 1) == '\n')*--o = 0;
      puts(Out);
    }
  }
  struct puts_write {
    ~puts_write() {
      flush1();
    }
  } _puts;
  inline void print2(int x) {
    printf("%d", x);
  }
  inline void println2(int x) {
    printf("%d\n", x);
  }
  inline void print2(char x) {
    printf("%c", x);
  }
  inline void println2(char x) {
    printf("%c\n", x);
  }
  inline void print2(ll x) {
#ifdef _WIN32
    printf("%I64d", x);
#else
#ifdef __linux
    printf("%lld", x);
#else
    puts("error:can recognize the system!");
#endif
#endif
  }
  inline void println2(ll x) {
    print2(x);
    printf("\n");
  }
  inline void println2() {
    printf("\n");
  }
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;


const int MAXN = 1000005;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int N, M;

//  2-d BIT
vector<int> data[MAXN];


void Add(int x, int y, int z) {
    for (int i = x; i <= N; i += i & -i)
        for (int j = y; j <= M; j += j & -j)
            data[i][j] += z;
}
int Sum(int x, int y) {
    int ans = 0;
    for (int i = x; i; i -= i & -i)
        for (int j = y; j; j -= j & -j)
            ans += data[i][j];
    return ans;
}

// end of 2-d BIT

vector<pair<int,int> > plants[MAXN];
vector<pair<pair<int,int>,pair<int,int>>> fertilizer[MAXN];

int main()
{
    //freopen("output.txt","w+",stdout);
    int T;
    //scanf("%d%d%d",&N,&M,&T);
    read(N);
    read(M);
    read(T);
    for(int i=1; i<=N+1; ++i)
        for(int j=1; j<=M+1; ++j)
            data[i].push_back(0);
    int plantype;
    for(int i=1; i<=N; ++i)
        for(int j=1; j<=M; ++j)
            {
                //scanf("%d",&plantype);
                read(plantype);
                plants[plantype].push_back({i,j});
            }
    int x1, y1, x2, y2, ftype;
    for(int i=1;i<=T;++i)
    {
        //scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&ftype);
        read(x1); read(y1); read(x2); read(y2); read(ftype);
        fertilizer[ftype].push_back({{x1,y1},{x2,y2}});
        Add(x1,y1,1);
        Add(x2+1,y1,-1);
        Add(x1,y2+1,-1);
        Add(x2+1,y2+1,1);
    }
    int res = 0;
    for(int i=1;i<=N*M;++i)
    {
        for(int j=0;j<fertilizer[i].size();++j)
        {
            Add(fertilizer[i][j].first.first,fertilizer[i][j].first.second,-1);
            Add(fertilizer[i][j].second.first+1,fertilizer[i][j].first.second,1);
            Add(fertilizer[i][j].first.first,fertilizer[i][j].second.second+1,1);
            Add(fertilizer[i][j].second.first+1,fertilizer[i][j].second.second+1,-1);
        }
        for(int j=0;j<plants[i].size();++j)
            if(Sum(plants[i][j].first,plants[i][j].second))
                res++;
        for(int j=0;j<fertilizer[i].size();++j)
        {
            Add(fertilizer[i][j].first.first,fertilizer[i][j].first.second,1);
            Add(fertilizer[i][j].second.first+1,fertilizer[i][j].first.second,-1);
            Add(fertilizer[i][j].first.first,fertilizer[i][j].second.second+1,-1);
            Add(fertilizer[i][j].second.first+1,fertilizer[i][j].second.second+1,1);
        }
    }
    //printf("%d\n",res);
    println(res);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Lfhase/article/details/81157619