Codeforces Round #590 (Div. 3)

Codeforces Round #590 (Div. 3)
A. Equalize Prices Again
题意:求平均值并且向上取整

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
#define LL long long
const int N=2e5+5;
const int mod=1e9+7;
int n,m;
int a[N];
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        int ans=0;
        for(int i=1;i<=n;i++)
            scanf("%d",a+i),ans+=a[i];
        printf("%d\n",(ans+n-1)/n);
    }
    return 0;
}

B:Social Network (hard version)
题意:有一个手机,能接受朋友的消息,按顺序有n条朋友的消息,但是同一时刻只能存在k个朋友的消息,如果>k个,则最找的那个消息丢失。
分析:直接模拟就行,但是由于朋友的id很大,所以要离散化,据说用unorder_map超时,建议看看相关文章,如何优雅的卡掉unorder_map。

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
#define LL long long
const int N=4e5+5;
const int mod=1e9+7;
int n,m,k;
int a[N],b[N];
bool vis[N];
map<int,int>mp;
int main(){
    cin>>n>>k;
    int x=0;
    for(int i=1;i<=n;i++){
        scanf("%d",a+i);
        if(mp.find(a[i])==mp.end())
            mp[a[i]]=++x;
    }

    int len=0,la=0;
    for(int i=1;i<=n;i++){
        int x=mp[a[i]];
        if(vis[x])
            continue;
        if(len==k)
            vis[mp[b[la-len+1]]]=false,len--;
        len++;
        b[++la]=a[i];
        vis[x]=true;
    }
    printf("%d\n",len);
    for(int i=la;i>=la-len+1;i--)
        printf("%d ",b[i]);
    return 0;
}

C:Pipes
题意:水管流水,起点(1,0),终点(2,n+1),有6总类型的水管,编号1,2,3,4,5,6,可以旋转,则{1,2}一样,{3,4,5,6}一样。问水流能不能留到终点。
分析:模拟一下发现水流方向唯一,直接模拟可行,赛中一直在写假dp,还写崩了,多亏群友提醒了一句

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
#define LL long long
const int N=2e5+5;
const int mod=1e9+7;
int n,m,k;
char a[3][N];
int main(){
    int t;
    cin>>t;
    while(t--){
        scanf("%d",&n);
        scanf("%s%s",a[1]+1,a[2]+1);
        for(int i=1;i<=2;i++)
            for(int j=1;j<=n;j++)
                if(a[i][j]<='2')
                    a[i][j]=1;
                else
                    a[i][j]=2;
        int x=1,y=1,z=(a[1][1]==1)?2:1;
        while(x>0&&x<=2&&y>=1&&y<=n){
            if(z==2){
                y++;
            } else if(z==0){
                x--;
            } else if(z==1){
                x++;
            }
            if(a[x][y]==2)
                if(z==2)
                    z=(x==2)?0:1;
                else
                    z=2;
          // printf("%d %d %d\n",x,y,z);
        }
        if(x==2&&y==(n+1))puts("YES");
        else puts("NO");
    }
    return 0;
}

D. Distinct Characters Queries
题意:有一个字符串 s, 有两种操作: 1 pos c,将s[pos]修改为c , 2 l r,查询l,r不同字符的数量。
分析:很容易想到两种写法。
写法1:维护26种字母1—i的数量,单点修改,区间查询。如果一个区间的数量>0则ans++.
写法2:26个set,每个set[i]存的是字符为i的坐标,修改直接find->erase->insert,然后用lower_bound()查找>=l的第一个位置,如果<=r,则ans++.

该题引申出另外一个题:给你n个数字a1,a2,…an,(1<=ai<=n);有Q组查询,每次查询[l,r]不同数的个数。题目链接:https://ac.nowcoder.com/acm/contest/139/J?&headNav=www

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
#define LL long long
const int N=1e5+5;
const int mod=1e9+7;
int n,m,k;
char a[N];
int c[27][N];
void upd(int x,int v,int *val){
    for(int i=x;i<=n;i+=(i&-i))
        val[i]+=v;
}
int sum(int x,int *val){
    int ans=0;
    for(int i=x;i;i-=i&-i)
        ans+=val[i];
    return  ans;
}
int main(){
    scanf("%s",a+1);
    n=strlen(a+1);
    for(int i=1;i<=n;i++)
        upd(i,1,c[a[i]-'a']);

    int q;
    scanf("%d",&q);
    while(q--){
        int op;
        scanf("%d",&op);
        if(op==1){
            int id;char ch;
            scanf("%d %c",&id,&ch);
            upd(id,-1,c[a[id]-'a']);
            upd(id,1,c[ch-'a']);
            a[id]=ch;
        } else {
            int l,r;
            scanf("%d%d",&l,&r);
            int ans=0;
            for(int i=0;i<26;i++){
                int x=sum(r,c[i])-sum(l-1,c[i]);
                if(x)
                    ans++;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

E:Special Permutations
题意:
定义排列 p i ( n ) = [ i , 1 , 2 , . . . . , i − 1 , i + 1 , i + 2... , n ] pi(n)=[i,1,2,....,i-1,i+1,i+2...,n] pi(n)=[i,1,2,....,i1,i+1,i+2...,n];
例如:
p 1 ( 4 ) = [ 1 , 2 , 3 , 4 ] p1(4)=[1,2,3,4] p1(4)=[1,2,3,4]
p 2 ( 4 ) = [ 2 , 1 , 3 , 4 ] p2(4)=[2,1,3,4] p2(4)=[2,1,3,4]
p 3 ( 4 ) = [ 3 , 1 , 2 , 4 ] p3(4)=[3,1,2,4] p3(4)=[3,1,2,4]
p 4 ( 4 ) = [ 4 , 1 , 2 , 3 ] p4(4)=[4,1,2,3] p4(4)=[4,1,2,3]

定义 p o s ( p , v a l ) pos(p,val) pos(p,val) 为 val 在排列 pi 中的位置.

p o s ( p i , v a l ) = { v a l + 1 v a l < i 1 v a l = i v a l v a l > i pos(pi,val)=\left\{\begin{matrix} val+1& val<i \\ 1& val=i\\ val& val>i \end{matrix}\right. pos(pi,val)=val+11valval<ival=ival>i

给你 m 个数字 x1,x2,…,xm(1<=xi<=n)

定义 f ( p ) = ∑ i = 1 m − 1 ∣ p o s ( p , x i ) − p o s ( p , x i + 1 ) ∣ f(p)=\sum_{i=1}^{m-1}|pos(p,x_{i})-pos(p,x_{i+1})| f(p)=i=1m1pos(p,xi)pos(p,xi+1)

f ( p 1 ) + f ( p 2 ) + . . f ( p n ) f(p1)+f(p2)+..f(pn) f(p1)+f(p2)+..f(pn)

分析:
考虑单个的 f ( p i ) f(pi) f(pi),如果排列 p 是正常的话,很容易计算出来,而 f ( p i ) f(pi) f(pi) 相比正常的有哪些区别呢。考虑单个 ∣ p o s ( p j , x i ) − p o s ( p j , x i + 1 ) ∣ |pos(pj,x_{i})-pos(pj,x_{i+1})| pos(pj,xi)pos(pj,xi+1) ,这里很容易得到几种情况,假设 x i < x i + 1 x_{i}<x_{i+1} xi<xi+1
一共有五种情况.

  1. x i > j x_{i}>j xi>j,和正常的情况一样,答案不变
  2. x i = j x_{i}=j xi=j, 变化量为 ∣ 1 − x i + 1 ∣ − ∣ x i − x i + 1 ∣ |1-x_{i+1}|-|x_{i}-x_{i+1}| 1xi+1xixi+1
  3. x i < j < x i + 1 x_{i}<j<x_{i+1} xi<j<xi+1,变化量为 ∣ x i + 1 − x i + 1 ∣ − ∣ x i − x i + 1 ∣ |x_{i}+1-x_{i+1}|-|x_{i}-x_{i+1}| xi+1xi+1xixi+1
  4. x i + 1 = j x_{i+1}=j xi+1=j,变化量为 ∣ x i + 1 − 1 ∣ − ∣ x i − x i + 1 ∣ |x_{i}+1-1|-|x_{i}-x_{i+1}| xi+11xixi+1
  5. x i + 1 < j x_{i+1}<j xi+1<j,和正常的情况一样,答案不变

很明显,对答案有影响的只有情况2,3,4,并且情况2和4对一个f(pj)有影响,情况3是对给一连续的 x i < j < x i + 1 x_{i}<j<x_{i+1} xi<j<xi+1 f ( p j ) f(pj) f(pj) +该变量,很容易想到用前缀和或者一些数据结构计算答案。

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
#define LL long long
#define ma make_pair
const int N=2e5+5;
const int mod=1e9+7;
int n,m,k;
int a[N];
LL val[N];
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        scanf("%d",a+i);
    LL x=0;
    for(int i=1;i<m;i++)
        x+=abs(a[i]-a[i+1]);
    val[1]=x;
    for(int i=1;i<m;i++){
        if(a[i]<a[i+1]){
            //1
            x=abs(a[i]-a[i+1]);
            x=abs(1-a[i+1])-x;
            val[a[i]]+=x;
            val[a[i]+1]-=x;
            //2
            x=abs(a[i]-a[i+1]);
            x=abs(a[i]+1-a[i+1])-x;
            val[a[i]+1]+=x;
            val[a[i+1]]-=x;
            //3
            x=abs(a[i]-a[i+1]);
            x=abs(a[i]+1-1)-x;
            val[a[i+1]]+=x;
            val[a[i+1]+1]-=x;
        } else if(a[i]==a[i+1]){
            ;
        } else {
            swap(a[i],a[i+1]);
            //1
            x=abs(a[i]-a[i+1]);
            x=abs(1-a[i+1])-x;
            val[a[i]]+=x;
            val[a[i]+1]-=x;
            //2
            x=abs(a[i]-a[i+1]);
            x=abs(a[i]+1-a[i+1])-x;
            val[a[i]+1]+=x;
            val[a[i+1]]-=x;
            //3
            x=abs(a[i]-a[i+1]);
            x=abs(a[i]+1-1)-x;
            val[a[i+1]]+=x;
            val[a[i+1]+1]-=x;
            swap(a[i],a[i+1]);
        }
    }
    for(int i=1;i<=n;i++)
        val[i]+=val[i-1],printf("%lld ",val[i]);
    return 0;
}

F:Yet Another Substring Reverse
SosDP

#include <bits/stdc++.h>
const int N=2e6+5;
const int M=20;
#define LL long long
using namespace std;
int n,dp[N],a[N];
char s[N];
int main(){
    cin>>s+1;
    for(int i=1;s[i];i++){
        int x=0,c=0;
        for(int j=i;s[j];j++){
            int t=1<<(s[j]-'a');
            if(x&t)break;
            x|=t;++c;
            dp[x]=c;
            a[x]=c;
        }
    }
    for(int i=0;i<=M;i++)
        for(int j=0;j<(1<<M);j++)
            if(j&(1<<i))
                dp[j]=max(dp[j],dp[j^(1<<i)]);
    int ans=0;
    for(int i=0;i<(1<<M);i++)
        ans=max(ans,a[i]+dp[i^((1<<M)-1)]);//,printf("%d %d\n",a[i],dp[i^((1<<M)-1)]);
    cout<<ans;
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值