Educational Codeforces Round 61 (Rated for Div. 2)(A,B,C.D,E,F,G)完整

题目链接:http://codeforces.com/contest/1132/problem

第一题(思维):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=1e2+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}

int cnt[4];

int main(){
    rep(i,0,4) cin>>cnt[i];
    if(cnt[2]==0){
        if(cnt[0]==cnt[3]) puts("1");
        else puts("0");
    }
    else{
        if(cnt[0]==cnt[3]&&cnt[0]) puts("1");
        else puts("0");
    }
    return 0;
}

第二题(模拟):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=3e5+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}

ll a[maxn];
ll n,m,sum=0;
ll b[maxn];

int main(){
    cin>>n;
    rep(i,0,n) {cin>>a[i];sum+=a[i];}
    sort(a,a+n);
    cin>>m;
    rep(i,0,m){
        cin>>b[i];
        cout<<sum-a[n-b[i]]<<endl;
    }
    return 0;
}

第三题(思维+前缀和+暴力枚举):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e3+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int n,q;
int l[maxn],r[maxn],tot=0;
int cnt[maxn],pre[maxn];///
int main(){
    cin>>n>>q;
    rep(i,0,q){
        cin>>l[i]>>r[i];
        cnt[l[i]]++,cnt[r[i]+1]--;
    }
    int ans=0,tmp;
    rep(i,0,q){
        tmp=tot=0;
        cnt[l[i]]--,cnt[r[i]+1]++;
        rep(j,1,n+1){
            tmp+=cnt[j];///维护前缀和
            if(tmp==1) pre[j]=pre[j-1]+1;
            else pre[j]=pre[j-1];///维护覆盖数为1的前缀和
            if(tmp) tot++;
        }
        rep(j,i+1,q){
            ans=max(ans,tot-pre[r[j]]+pre[l[j]-1]);
        }
        cnt[l[i]]++,cnt[r[i]+1]--;
    }
    cout<<ans<<'\n';
    return 0;
}

第四题(贪心+二分+优先队列+剪枝):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=2e5+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
每个同学电脑有初始电量和电量消耗速度,
这堂课有k分钟,其损耗过程有note描述。
现在有个输出x,每分钟可以指定一个电脑并充电x,
问要维护每位同学电脑电量始终不小于零,其最小的x是多少。

题目分析:
这道题思路倒是蛮容易想的,就是细节比较多!
可以看出是二分,并且二分上界是12次方,题目凑好的,
不然过程中可能会有越界。
我们用优先队列维护过程中的电脑电量,
我们肯定优先选择支撑分钟最少的电脑,
如果电脑支撑分钟一样则无需细分,不难发现:
如果因为这次充电次数增加,那么下一次会轮到下一个最少的,
如果情况本身会超出界限,那么最终结果不会因为其顺序而影响,
关于这一点稍微模拟下不难发现。
那么对于每次取出来的节点,判定是否符合要求,如果符合则充电并再丢进去。
这里时间常数比较大,因为优先队列本身自带log,
下面是几个剪枝点:
上界可以预处理出来,这里我并没有这样做。。。
如果取出的最少次数都大于k那么一定可以成功(第二个if)
六十四位除法,关于次数的比较我们不要在优先队列的优先级比较里面写除法
而通过增加变量的方式来代替(重点:看来计组还是要好好学的。。。)
时间复杂度:O(nlog(1e12)*logn)
*/
ll n,k;
ll a[maxn],b[maxn];
struct node{
    ll x,y,tim;
    bool operator<(const node& q) const {
        return tim>q.tim;///剪枝
    }
};
bool judge(ll x){
    priority_queue<node> pq;
    rep(i,1,n+1) pq.push(node{a[i],b[i],a[i]/b[i]});
    for(ll i=0;i<k;i++){
        node tp=pq.top();pq.pop();
        if(tp.x-i*tp.y<0) return false;
        if(tp.x/tp.y>k) return true;///剪枝
        tp.x+=x;pq.push(node{tp.x,tp.y,tp.x/tp.y});
    }
    return true;
}
int main(){
    scanf("%lld%lld",&n,&k);
    rep(i,1,n+1) scanf("%lld",&a[i]);
    rep(i,1,n+1) scanf("%lld",&b[i]);
    ll l=0,r=2e12;///这里还有一个加速点,可以预判定其上界
    while(l<r){
        ll mid=l+r>>1;
        if(judge(mid)) r=mid;
        else l=mid+1;
    }
    if(r==2e12) puts("-1");
    else printf("%lld\n",r);
    return 0;
}

第五题(背包优化):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=1e5+100;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定八种物品每种物品价值为i,(1~8),
然后给定一个w,问能达到的不大于w的值最大值是多少。
w和物品个数都非常大。

题目分析:
比较神仙的一道背包题目吧算是,
我是看了题解才有想法的。
对于1到8,其单独取都可以凑成840(取八个数最小公倍数)
就是说假定答案是cnt1,cnt2,...cnt8,
那么我们总是可以从中剥离出840的整数倍,
这是答案的性质,利用这个性质我们进行优化。
因为我们对每一种答案都把840的整数倍剥离出来了,
所以最后实质上要进行的背包其容量最大是8*840,
然后每种物品个数也不超过840了,对于这个情况背包时间复杂度是允许的。
然后我们顺便维护下对于0到840中每一种最后达到的状态其取到的840的
个数的最大值,这就是传统的DP了,上面两个DP可以放到一起写,标志状态为-1即可。
然后对于8*840的每一种状态,我们都贪心的选取840来填充,其填充上界很明显是:
(w-j)/840,与dp数组中得出的值取最小即可,这样构成答案的候选者。
当然空间优化也是可以的。
*/
ll w;
ll cnt[8],dp[10][8*850];
int main(){
    cin>>w;
    rep(i,0,8) cin>>cnt[i];
    mst(dp,-1),dp[0][0]=0;
    rep(i,0,8) rep(j,0,8*840+1) if(dp[i][j]!=-1){
        ll tmp=min(1LL*840/(i+1),cnt[i]);
        rep(k,0,tmp+1)
            dp[i+1][j+k*(i+1)]=max(dp[i+1][j+k*(i+1)],dp[i][j]+(cnt[i]-k)/(840/(i+1)));
    }
    ll ans=0;
    rep(i,0,8*840+1) if(dp[8][i]!=-1){
        if(i>w) continue;
        ans=max(ans,i+min((w-i)/840,dp[8][i])*840);
    }
    cout<<ans<<'\n';
    return 0;
}

 

第六题(区间DP):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e2+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int n,tn=0,ans=0,INF;
char s[maxn];
int dp[maxn][maxn];
int main(){
    scanf("%d%s",&n,s+1);
    rep(i,1,n+1){
        s[++tn]=s[i];
        while(i+1<=n&&s[i+1]==s[i])
            i++;
    }
    n=tn;
    mst(dp,0xf),INF=dp[0][0];
    rep(i,1,n+1) dp[i][i]=1;
    rep(i,2,n+1) rep(j,1,n-i+2){
        int l=j,r=j+i-1;
        if(s[l]==s[r]) dp[l][r]=dp[l+1][r-1]+1;
        else dp[l][r]=min(dp[l+1][r],dp[l][r-1])+1;
        rep(k,l,r+1) dp[l][r]=min(dp[l][r],dp[l][k]+dp[k][r]-1);
    }
    cout<<dp[1][n]<<'\n';
    return 0;
}

第七题(线段树维护极值+DFS序+单调栈):

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=1e6+5;
const int ub=1e6;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
int n,k,a[maxn];
int sk[maxn],l,r,rt=1e6+1;///虚点
vector<int> g[maxn];
int pl[maxn],pr[maxn],tot=0;
void dfs(int u,int pre){
    pl[u]=++tot;
    for(int i=0;i<g[u].size();i++){
        if(g[u][i]==pre) continue;
        dfs(g[u][i],u);
    }
    pr[u]=tot;
}
///线段树
int tree[maxn<<3],maxv[maxn<<3],lazy[maxn<<3];
void build(lrt){
    lazy[rt]=0;
    if(l==r) return ;
    int mid=l+r>>1;
    build(lson),build(rson);
}
void pushdown(int rt,int l,int r){
    int mid=l+r>>1;
    if(lazy[rt]){
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        maxv[rt<<1]+=lazy[rt];
        maxv[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void update(lrt,int L,int R,int v){
    if(L<=l&&r<=R){
        maxv[rt]+=v;
        lazy[rt]+=v;
        return ;
    }
    pushdown(rt,l,r);
    int mid=l+r>>1;
    if(L<=mid) update(lson,L,R,v);
    if(mid<R) update(rson,L,R,v);
    maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
int query(lrt,int L,int R){
    if(L<=l&&r<=R) return maxv[rt];
    pushdown(rt,l,r);
    int mid=l+r>>1,ans=0;
    if(L<=mid) ans=max(ans,query(lson,L,R));
    if(mid<R) ans=max(ans,query(rson,L,R));
    return ans;
}
int main(){
    cin>>n>>k;
    l=1,r=l-1;
    rep(i,1,n+1){
        cin>>a[i];
        while(r>=l&&a[sk[r]]<a[i]){
            g[i].push_back(sk[r]);
            g[sk[r]].push_back(i);
            r--;
        }
        sk[++r]=i;
    }
    rep(i,l,r+1){
        g[sk[i]].push_back(rt);
        g[rt].push_back(sk[i]);
    }
    dfs(rt,0);///建立dfs序
    build(1,tot,1);
    rep(i,1,k+1) update(1,tot,1,pl[i],pr[i],1);
    rep(i,1,n+2-k){
        cout<<query(1,tot,1,1,tot)<<" ";
        update(1,tot,1,pl[i],pr[i],-1);
        if(i+k<=n)
            update(1,tot,1,pl[i+k],pr[i+k],1);
    }
    return 0;
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值