zoukankan      html  css  js  c++  java
  • Codeforces Round #536 (Div. 2)

    A. Lunar New Year and Cross Counting

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll; 
    const int maxn=510;
    int n;
    char s[maxn][maxn];
    int cnt;
    int main(){
        while(cin>>n)
        {
            for(int i=1;i<=n;i++){
                scanf("%s",s[i]+1);
            }
            cnt=0;
            for(int i=2;i<n;i++)
            {
                for(int j=2;j<n;j++)
                {
                    if(s[i-1][j-1]=='X'&&s[i+1][j-1]=='X'&&s[i][j]=='X'&&s[i-1][j+1]=='X'&&s[i+1][j+1]=='X')cnt++;
                }
            }
            cout<<cnt<<endl;
        }
    }
    View Code

    B. Lunar New Year and Food Ordering

    题意:(翻译来自洛谷)

    思路:

      如果在一个菜品够买的情况下,当然是直接买,但是如果不够的话,就需要按照一定的优先级来维护这些物品了,显然是优先队列,优先队列中的元素只存储id和cost,然后剩余的量用一个r数组来保存,如果从优先队列里pop出来的东西剩余量为0就直接扔掉。

      B题居然会这么麻烦。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll; 
    const int maxn=100010;
    int n,m;
    struct node{
        int id;
        ll cost;
        friend bool operator<(const node &a,const node &b){
            if(a.cost-b.cost)return a.cost>b.cost;
            return a.id>b.id;
        }
    }a[maxn];
    priority_queue<node >q;
    ll r[maxn];
    ll ans[maxn];
    int main(){
        while(cin>>n>>m){
            clr(ans,0);
            while(!q.empty())q.pop();
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&r[i]);
            }
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i].cost);
                a[i].id=i;
                q.push(a[i]);
            }
            for(int i=1;i<=m;i++)
            {
                int t;
                ll d;
                scanf("%d%lld",&t,&d);
                ans[i]+=min(d,r[t])*a[t].cost;
                ll v=min(d,r[t]);
                d-=v;
                r[t]-=v;
                while(d>0){
                    if(q.empty())break;
                    node s=q.top();
                    if(r[s.id]==0){
                        q.pop();
                        continue;
                    }
                    v=min(d,r[s.id]);
                    ans[i]+=v*a[s.id].cost;
                    d-=v;
                    r[s.id]-=v;
                }
                if(d>0){
                    ans[i]=0;
                }
            }
            for(int i=1;i<=m;i++)
            {
                printf("%lld
    ",ans[i]);
            }
        }
    }
    View Code

    C. Lunar New Year and Number Division

    思路:可以证明(等会证明)要两两分组,并且从小到大排,然后i 和n-i+1位置结合是最小的。

    上面结论的两部分,后面一部分很好证明,个人认为前面的一部分有点难证明,其他博客的证明对这个两两分组最优讲的都不是很详细,某天在群里和大佬讨论后,大佬证明两两结合比三三结合更优。

    这里面a是两个数字相加,d也是两个数字的相加,所以就是两两组合和三三组合。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll; 
    const int maxn=300010;
    int n;
    ll a[maxn];
    ll ans;
    int main(){
        while(cin>>n)
        {
            ans=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);    
    
        }
            sort(a+1,a+1+n);
            for(int i=1;i<=n/2;i++)
            {
                ans+=(a[i]+a[n-i+1])*(a[i]+a[n-i+1]);
            }
            cout<<ans<<endl;
        }
    }
    View Code

    D. Lunar New Year and a Wander

    题意:在一个连通图上从1出发,每次到一个没有到达过的城市,记录标号,城市可以来回走,求字典序最小的路径。

    思路:每到一个新城市,就把这个城市可以到达的城市标号塞入一个优先队列,优先弹出最小的标号即可。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll; 
    const int maxn=100010;
    vector<int >ve[maxn];
    bool vis[maxn];
    int n,m,u,v;
    int ans[maxn],tot;
    void init(){
        for(int i=1;i<=n;i++)
        {
            ve[i].clear();
        }
        clr(vis,0);
        tot=0;
    }
    priority_queue<int >q;
    int main(){
        while(cin>>n>>m)
        {
            init();
            while(m--)
            {
                scanf("%d%d",&u,&v);
                ve[u].push_back(v);
                ve[v].push_back(u);
            }
            q.push(-1);
            vis[1]=1;
            while(tot<n)
            {
                int u=-q.top();
                q.pop();
                ans[++tot]=u;
                for(auto it:ve[u]){
                    if(vis[it])continue;
                    vis[it]=1;
                    q.push(-it);
                }
            }
            for(int i=1;i<=tot;i++)
            {
                printf("%d%c",ans[i]," 
    "[i==tot]);
            }
        }
    }
    View Code

    E. Lunar New Year and Red Envelopes

    题意:翻译来自洛谷

    思路:

      将红包按价格从小打到排序,相同的按d从小到大排序,然后依次用线段树来更新,就可以得到在任意一秒如果抢红包,抢的是哪个红包,由于这个排序,所以如果后面的红包把前面的红包覆盖掉了,也是优先级高的覆盖了优先级低的。

      然后就是dp了,如果不考虑d的话,我们从前往后用一个二维dp就很好做了,但是现在这个d存在,要怎么办呢,我们倒着dp,并且转移的时候 $ f[i][j]=min(f[i+1][j-1],f[a[x].d+1][j]+a[x].w) $ x就是在第i秒抢到的红包标号。

      由于s<t<d,所以这个dp保证了一个红包不会被抢两次。

    吐槽自己,居然想用普通的树状数组完成区间改值,单点查询的操作,蠢的一批。。

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll; 
    const int maxn=100010;
    int n,m,k;
    ll c[maxn];
    ll f[maxn][210];
    struct node{
        int s,t,d;
        ll w;
        friend bool operator<(const node &a,const node &b)
        {
            if(a.w!=b.w)return a.w<b.w;;
            return a.d<b.d;
        }
    }a[maxn];
    ll num[maxn];
    struct segNode{
        ll sum,lazy;
    }tr[maxn<<2];
    void build(int o,int l,int r){
        if(l==r){
            tr[o].sum=0;
            tr[o].lazy=-1;
            return ;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build((o<<1)|1,mid+1,r);
        tr[o].sum=tr[o<<1].sum+tr[(o<<1)|1].sum;
        tr[o].lazy=-1;
    }
    void pushup(int o){
        tr[o].sum=tr[o<<1].sum+tr[o<<1|1].sum;
    }
    void pushdown(int o,int l,int r){
        if(tr[o].lazy!=-1){
            tr[o<<1].lazy=tr[o].lazy;
            tr[o<<1|1].lazy=tr[o].lazy;
            int mid=(l+r)>>1;
            tr[o<<1].sum=tr[o].lazy*(mid-l+1);
            tr[o<<1|1].sum=tr[o].lazy*(r-mid);
            tr[o].lazy=-1;
        }
    }
    void update(int o,int l,int r,int ql,int qr,ll val){
        if(ql<=l&&r<=qr){
            tr[o].lazy=val;
            tr[o].sum=val*(r-l+1);
            return;
        }
        pushdown(o,l,r);
        int mid=l+((r-l)>>1);
        if(ql<=mid)update(o<<1,l,mid,ql,qr,val);
        if(qr>=mid+1)update(o<<1|1,mid+1,r,ql,qr,val);
        pushup(o);
    }
    ll query(int o,int l,int r,int ql,int qr){
        if(ql<=l&&qr>=r)return tr[o].sum;
        pushdown(o,l,r);
        int mid=(l+r)>>1;
        ll ans=0;
        if(ql<=mid)ans=query(o<<1,l,mid,ql,qr);
        if(qr>=mid+1)ans+=query(o<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    int main(){
        while(cin>>n>>m>>k)
        {
            clr(c,0);
            clr(num,0);
            clr(f,0);
            for(int i=1;i<=k;i++)
            {
                scanf("%d%d%d%lld",&a[i].s,&a[i].t,&a[i].d,&a[i].w);
            }
            sort(a+1,a+1+k);
            build(1,1,n);
            for(int i=1;i<=k;i++)
            {
                update(1,1,n,a[i].s,a[i].t,(ll)i);
            }
            for(int i=1;i<=n;i++)
            {
                num[i]=query(1,1,n,i,i);
            }
            for(int i=n;i>0;i--)
            {
                if(num[i]==0)
                {
                    for(int j=0;j<=m;j++)
                    {
                        f[i][j]=f[i+1][j];
                    }
                    continue;
                }
                int x=num[i];
                f[i][0]=f[a[x].d+1][0]+a[x].w;
                for(int j=1;j<=m;j++)
                {
                    f[i][j]=min(f[i+1][j-1],f[a[x].d+1][j]+a[x].w);
                }
            }
            printf("%lld
    ",f[1][m]);
        }
    }
    View Code

    F. Lunar New Year and a Recursive Sequence

  • 相关阅读:
    面试题:最小的K个数
    面试题:反转链表
    面试题:二进制中1的个数
    数据结构之二叉树
    Serializable-源码分析
    归并、希尔、快速排序
    栈与队列
    简单排序(冒泡、选择、插入)
    Shiro 框架认证和授权
    mybatis select查询使用返回结果为resultMap
  • 原文地址:https://www.cnblogs.com/mountaink/p/10358476.html
Copyright © 2011-2022 走看看