Fork me on GitHub

2018-2019 ACM-ICPC, NEERC, Southern Subregional Contest, Qualification Stage_组队训练

A. Coffee Break

题意:Monocarp得到一份工作,每天要工作 m 分钟,他有一个爱好,喜欢在休息的时候喝咖啡,但是他的老板不乐意了,就给他规定了个时间 d,在 d 分钟内只能喝一杯咖啡。现给出Monocarp喝 n 杯咖啡的时间点,问最少需要几天喝完?并输出每个时间点的咖啡在第几天喝。

题解:优先队列

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e6+10;
struct node{
    ll a;
    int id;
}s[maxn];
bool cmp1(node x,node y)
{
    return x.a<y.a;
}
ll ans[maxn];
typedef pair<ll,ll> pre;
struct cmp{
    bool operator ()(const pre p1,const pre p2){
        return p1.second>p2.second; 
    }
};

ll num[maxn];
int main(){
    priority_queue< pre,vector<pre>,cmp >q;
    ll n,m,d;
    cin>>n>>m>>d;
    for(int i=1;i<=n;i++){
        scanf("%lld",&s[i].a);
        s[i].id=i;
    }
    sort(s+1,s+n+1,cmp1);
    q.push(make_pair(1,s[1].a));
    ans[s[1].id]=1;
    int day=1;
    for(int i=2;i<=n;i++){
        //cout<<q.top().first<<endl;
        if(q.top().second+d+1>s[i].a){
            day++;
            q.push(make_pair(day,s[i].a));
            ans[s[i].id]=day;
        }else{
            int dd=q.top().first;
            q.pop();
            ans[s[i].id]=dd;
            q.push(make_pair(dd,s[i].a));
        }
    }
     
    printf("%d\n",day);
    for(int i=1;i<=n;i++){
        printf("%lld%c",ans[i]," \n"[i==n]);
    }
}

B. Glider:

题意:给n个区间和高度h,区间水平移动,非区间每一步就向下移动一步,起点任取,问最远到哪;

题解:二分+前缀和

#include<bits/stdc++.h>
#define ll long long int
using namespace std;
const int maxn = 2e5+5;
struct node {
    ll s,e;
    ll t;
}x[maxn];
ll len[maxn];
ll pre[maxn];
ll plen[maxn];
int main()
{
    ll n,m;
    cin>>n>>m;
    ll maxx = 0;
    for(int i=1;i<=n;i++)
    {
        cin>>x[i].s >>x[i].e;
        x[i].t = x[i].e - x[i].s ;
    }
    int count = 0;
    for(int i=2;i<=n;i++)
    {
        len[i] = x[i].s - x[i-1].e;
    }
    for(int i=2;i<=n;i++)
    {
        plen[i] = plen[i-1] + len[i];
     } 
    for(int i=1;i<=n;i++)
    {
        pre[i] = pre[i-1] + x[i].e - x[i].s; 
    } 
    for(int i=1;i<=n;i++)
    {
        ll te = x[i].e + 1;
        ll found = m - 1;
        int left = 1,right = i;
        int maxxx = 0;
        while(left <= right)
        {
            int mid = (left + right)>>1;
            ll tt = plen[i] - plen[i-mid+1];
            if(tt<=found)
            {
                maxxx = max(maxxx ,mid);
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
        ll Maxx = found + pre[i] - pre[i - maxxx] + 1;
        maxx = max(maxx ,Maxx);
    //    cout<<i<<" "<<Maxx<<" "<<maxxx<<endl;
    }
    cout<<maxx<<endl;
 } 

C. Bacteria

题意:给N个数,只有相同的两个数才能结合起来,加在一起。比如说2只有和2结合,成为4。

思路:最后合成的一定是2的幂次的倍数,先判断每个数是不是2的幂次的倍数,然后找最小的2的幂次大于他们的和就是那个数了。直接模拟

#include<bits/stdc++.h>
/*#include<cstring>
#include<set>
#include<map> 
#include<iostream>
#include<algorithm>
#if(__cplusplus == 201103L)
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
namespace std
{
    using std::tr1::unordered_map;
    using std::tr1::unordered_set;
}
#endif*/ 
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define pb push_back
#define de(x) cout<<x<<endl
#define dd(x) cout<<x<<" "
#define is insert
using namespace std;
const int maxn =10001000;
const int mod = 1e9+7;
typedef pair<ll, ll> p1;
typedef pair< ll, pair<ll,ll > >p2;
inline int rd(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void out(int a) {if(a<0)putchar('-'),a=-a;if(a>=10)out(a/10);putchar(a%10+'0');}
const int INF = 0x3f3f3f3f;
int MOVE[4][2]={
    {0,1},
    {1,0},
    {0,-1},
    {-1,0},
};
ll ok(ll x){
    ll y=1;
    while(1){
        //cout<<y<<endl;
        if(x>=y){
            y*=2;
        }
        else{
            break;
        }
    }
    return y/2;
}
ll a[200005];
void run()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    int pp = a[1];
    for(int i=1;i<=n;i++)
    {
        int xx = a[i]/pp;
        if(a[i]%a[1]!=0)
        {
            puts("-1");
            return;
        }
        while(xx%2==0)
        {
            xx/=2;
        }
        //cout<<xx<<endl;
        if(xx!=1)
        {
            puts("-1");
            return;
        }
        a[i] = a[i]/pp;
    }
    ll sum = 0;
    for(int i=1;i<=n;i++)
    {
        sum+=a[i];
    }
    ll xx = 1;
    while(xx<sum)
    {
        xx*=2;
    }
    ll ans = xx - sum;
//    cout<<ans<<endl;
    ll yy=xx/2;
    ll num=0;
    while(ans>1){
        //cout<<ok(ans)<<endl;
        ans-=ok(ans);
        //cout<<ans<<endl;
        num++;
    }
//    cout<<num<<endl;
    if(ans==1) num++;
    cout<<num<<endl;
 } 
signed main()
{
    //std::ios::sync_with_stdio(false);
    run();
 } 
 

D. Masquerade strikes back

题意:给出n个数,看是否能由不同的有序队相乘得来。

题解:直接模拟,暴力求解,然后用vector优化。

#include<bits/stdc++.h>
/*#include<cstring>
#include<set>
#include<map> 
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#if(__cplusplus == 201103L)
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
namespace std
{
    using std::tr1::unordered_map;
    using std::tr1::unordered_set;
}
#endif*/
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define pb push_back
#define de(x) cout<<x<<endl
#define dd(x) cout<<x<<" "
#define is insert
using namespace std;
const int maxn =2001000;
const int mod = 1e9+7;
typedef pair<ll, ll> p1;
typedef pair< ll, pair<ll,ll > >p2;
inline int rd(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void out(int a) {if(a<0)putchar('-'),a=-a;if(a>=10)out(a/10);putchar(a%10+'0');}
const int INF = 0x3f3f3f3f;
int MOVE[4][2]={
    {0,1},
    {1,0},
    {0,-1},
    {-1,0},
};

int a[maxn];
int b[maxn],c[maxn];
vector<int>v[200005];
vector<int>::iterator it;
int mm[10000005];
void run()
{
    int n ;
    scanf("%d",&n);
    int qq = 1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(!mm[a[i]])
        {
            mm[a[i]] = qq;
            qq++;
            for(int j=1;j*j<=a[i];j++)
            {
                if(a[i]%j==0)
                {
                    if(j!=a[i]/j)
                    {
                        v[qq-1].pb(j);
                        v[qq-1].pb(a[i]/j);
                    }
                    else{
                        v[qq-1].pb(j);
                    }
                }
            }
            b[i] = 1,c[i] = a[i];
            v[qq-1].erase(v[qq-1].begin());
        }
        else{ 
            int pp = mm[a[i]]; 
            if(v[pp].size() == 0)
            {
                printf("NO");
                return;
            }
            it = v[pp].begin();
            b[i] = *it,c[i] = a[i]/(*it);
            v[pp].erase(v[pp].begin());
        }
    }
    printf("YES\n");
    for(int i=1;i<=n;i++)
    {
        out(b[i]),printf(" "),out(c[i]),printf("\n");
    }
 } 
signed main()
{
    //std::ios::sync_with_stdio(false);
    run();
 } 
 

E. Painting the Fence

题意:给n个初始颜色,m次涂色,每指定一种颜色这种颜色最左到最右染色,问最后的颜色序列

题解:模拟然后用set来优化,set来存所在数的下标就行

#include<bits/stdc++.h>
#define ll long long int
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
const int maxn = 300010;
int a[maxn];
set<int>s[maxn];
set<int>::iterator it;
set<int>::reverse_iterator rit;
int vis[maxn];
int ans[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        s[a[i]].insert(i);
    }
    int m;
    cin>>m;
    while(m--)
    {
        int x;
        cin>>x;
        if(vis[x]||s[x].size()<2)
        {
            continue;
        }
        it = s[x].begin();
        rit = s[x].rbegin();
        int l = *it + 1;
        int r = *rit - 1;
        for(int j = l;j <= r;j ++)
        {
            s[a[j]].erase(j);
            if(vis[a[j]]&&s[a[j]].size()>0)
            {
                it = s[a[j]].begin();
                j = *it;
                s[a[j]].erase(j);
            }
        }
        vis[x] = 1;
    }
    int count = 0;
    for(int i=1;i<=n;i++)
    {
        if(s[a[i]].size()>1&&vis[a[i]])
        {
            it = s[a[i]].begin();
            rit = s[a[i]].rbegin();
            for(int j = *it ;j <= *rit ;j ++)
            {
                ans[j] = a[i];
            }
            i = *rit;
        }
        else{
            ans[i] = a[i];
        }
    }
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
 } 

F. Tickets

前缀和

#include<bits/stdc++.h>
/*#include<cstring>
#include<set>
#include<map> 
#include<iostream>
#include<algorithm>
#if(__cplusplus == 201103L)
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
namespace std
{
    using std::tr1::unordered_map;
    using std::tr1::unordered_set;
}
#endif*/ 
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define pb push_back
#define de(x) cout<<x<<endl
#define dd(x) cout<<x<<" "
#define is insert
using namespace std;
const int maxn =10001000;
const int mod = 1e9+7;
typedef pair<ll, ll> p1;
typedef pair< ll, pair<ll,ll > >p2;
inline int rd(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void out(int a) {if(a<0)putchar('-'),a=-a;if(a>=10)out(a/10);putchar(a%10+'0');}
const int INF = 0x3f3f3f3f;
int MOVE[4][2]={
    {0,1},
    {1,0},
    {0,-1},
    {-1,0},
};
int sum(int num)
{
    int x1=0,x2=0,pos=1;
    while(num>0){
        int x=num%10;
        num/=10;
        if(pos<=3){
            x1+=x; 
        }else{
            x2+=x;
        }
        pos++;
    }
    return abs(x2-x1);
}
int a[maxn];
int p[maxn];
void init()
{
    for(int i=0;i<=999999;i++){
        for(int j=0;j<sum(i);j++){
            p[i]+=a[j];
        }
        a[sum(i)]++;    
    }
}
void run()
{
    init();
    int num;
    int t = rd();
    while(t--)
    {
        scanf("%d",&num);
        printf("%d\n",p[num]); 
    }
    
 } 
signed main()
{
    //std::ios::sync_with_stdio(false);
    run();
 } 
 

G Tree Reconstruction

题意:n个点,给出n-1条边  每条边的左右部分的 最大节点编号  是否能还原这个树

题解:首先给出的两点一定要有一个是节点n,否则一定不符合然后我们保存一下较小的那个节点,排序,从小到大开始连接,若遇见一样的,那就看是否有更小的节点没有连接,这样我们构造一个一条线的树就可以了

#include<bits/stdc++.h>
#define ll long long int
using namespace std;

int minn[1010];
int tree[1010];
set<int>s;
set<int>::iterator it;
int main()
{
    int n;
    cin>>n;
    int ans = 0;
    for(int i=1;i<=n-1;i++)
    {
        int x,y;
        cin>>x>>y;
        if(max(x,y) == n) ans++;
        minn[i] = min(x,y);
        s.insert(i);
        //cout<<i<<endl;
    }
    if(ans!=n-1)
    {
        puts("NO");
        return 0;
    }
    sort(minn+1,minn+n);
    s.insert(n);
    tree[1] = minn[1];
    s.erase(minn[1]);
    for(int i=2;i<=n-1;i++)
    {
        it = s.begin();
        //cout<<*it<<endl;
        if(minn[i] == minn[i-1])
        { 
            if(*it > minn[i])
            {
                puts("NO");
                return 0;
            }
            else{
                //cout<<*it<<endl;
                tree[i] = *it;
                s.erase(*it);
            }
        }
        else{
            tree[i] = minn[i];
            s.erase(minn[i]);
        }
    }
    tree[n] = n;
    puts("YES");
    for(int i=2;i<=n;i++)
    {
        printf("%d %d\n",tree[i-1],tree[i]);
    }
 } 

H. Theater Square

简单数学

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e6+10;

int main()
{
    int n,m,sum=0;
    int x1,y1,x2,y2;
    cin>>n>>m;
    cin>>x1>>y1>>x2>>y2;
    int d=(x2-x1+1);
    if(y1%2==0)sum+=d;
    if((m-y2)%2==1)sum+=d;
    if(m%2==1){
        sum+=(n-d);
    } 
    printf("%d\n",sum/2+(sum%2));
}

I. Heist

签到题

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int a[maxn];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    sort(a,a+n);
    int maxx,minx;
    maxx=a[n-1];
    minx=a[0];
    printf("%d\n",a[n-1]-a[0]+1-n);
}

J Buying a TV Set

签到题:

#include<bits/stdc++.h>
/*#include<cstring>
#include<set>
#include<map> 
#include<iostream>
#include<algorithm>
#if(__cplusplus == 201103L)
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
namespace std
{
    using std::tr1::unordered_map;
    using std::tr1::unordered_set;
}
#endif*/ 
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define pb push_back
#define de(x) cout<<x<<endl
#define dd(x) cout<<x<<" "
#define is insert
using namespace std;
const int maxn =10001000;
const int mod = 1e9+7;
typedef pair<ll, ll> p1;
typedef pair< ll, pair<ll,ll > >p2;
inline int rd(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void out(int a) {if(a<0)putchar('-'),a=-a;if(a>=10)out(a/10);putchar(a%10+'0');}
const int INF = 0x3f3f3f3f;
int MOVE[4][2]={
    {0,1},
    {1,0},
    {0,-1},
    {-1,0},
};

void run()
{
    ll a,b,x,y;
    cin>>a>>b>>x>>y;
    ll ans = __gcd(x,y);
    ll xx = x/ans;
    ll yy = y/ans;
    ll maxx1 = a/xx,maxx2 = b/yy;
    if(min(maxx1,maxx2) == 0)
    {
        puts("0");
        return;
    }
    ll left = 0,right = min(maxx1,maxx2);
    ll maxx = 0;
    while(left <= right)
    {
        ll mid = (left + right)>>1;
        if(xx*mid<=a&&yy*mid<=b)
        {
            left = mid + 1;
            maxx = max(maxx,mid);
        }
        else
        {
            right = mid - 1; 
        } 
    }
    cout<<maxx<<endl;
 } 
signed main()
{
    //std::ios::sync_with_stdio(false);
    run();
 } 
 

(K) Medians and Partition

思维题:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,m,k;
    scanf("%d%d ",&n,&m);
    int a=0,b=0;
    while(n--){
        scanf("%d",&k);
        if(k>=m) a++;
        else b++;
    }
    printf("%d\n",max(a-b,0));
}

L. Ray in the tube

待补

posted @ 2021-03-20 00:17  lcsdsg  阅读(54)  评论(0)    收藏  举报
【推荐】 程序员网址大全  |  EF CodeFirst  |  百度地图.NET  |  MyNPOI  |  开源  |  我的皮肤  |  ASP.NET MVC4  |  前端提升   |  LINQ   |  WCF   |  EasyUI  |