码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 788 (Div. 1)

时间:2019-02-21 21:38:22      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:定义函数   input   不同   i++   long   bool   names   .so   tput   

788 A

题意

给你一个长度为 \(n\) 的序列 \(a\) ,定义函数
技术图片

其中 \(1\le l<r\le n\)
求对于所有可能的 \(l,r,f(l,r)\) 的最大值
\((2\le n\le 100000)\)

Examples

Input
5
1 4 2 3 1
Output
3
Input
4
1 5 4 7
Output
6

\(dp[i][0]\) 为未计算当前节点能达到的最大值, \(dp[i][1]\) 为计算当前节点能达到的最大值.
每枚举一个 \(i\)\(ans\) 都取一遍 \(\max\)
转移方程:

dp[i][0]=max(dp[i-1][1]-s[i],0);
dp[i][1]=max(dp[i-1][0]+s[i],s[i]);
ans=max(ans,max(dp[i][0],dp[i][1]));

788 B

题意

给你一张图,有自环,无重边,找出一条路径,使得它经过所有的边,且经过这些边的其中两条恰好 \(1\) 次,经过其他边恰好 \(2\) 次。
求出所有满足条件的路径数量。
\((1\le n,m\le 10^6)\)

Examples

Input
5 4
1 2
1 3
1 4
1 5
Output
6
Input
5 3
1 2
2 3
4 5
Output
0
Input
2 2
1 1
1 2
Output
1

设对于一对边,如果存在一条合法路径,使这条路径经过着两条边恰好 \(1\) 次,那么我们称这一对边是合法的。
经过一番波折,我们推出:两两非自环边搭配必定合法;自环与任意一条边(可以是自环,也可以不是)搭配都合法。
最后累计。

788 C

题意

\(k\) 瓶不同浓度的可乐,每瓶1000mL,现在要求配一瓶浓度为 \(n\) mL/1000mL 的可乐,问最少需要几瓶。\((0?≤?n?≤?1000, 1?≤?k?≤?10^6)\)

Examples

Input
400 4
100 300 450 500
Output
2
Input
50 2
100 25
Output
3

将每瓶饮料的浓度减去 \(n\)
题目可以转换为求一条最短路,这条最短路上的权值之和为 \(0\) ,且长度最小
我们发现,合法的浓度不会超过 \(2000\)
于是用dijkstra搞一下就好了
后来发现其实只需要一个bfs!!

788 D

题意

交互题
平面上有 \(n\) 条直线,与坐标轴平行。现在,你有至多 \(3×10^5\) 次机会询问,每次询问形如 \(0\;x\;y\) ,系统将返回与这个点距离最近的直线到它的距离。
直到已知所有直线的解析式,要求输出。
\((1\le n\le 2×10^4,直线坐标,询问坐标\le 10^8)\)

Example

Input
1
1
3
2
Output
0 1 2
0 -2 -2
0 5 6
0 -2 2
1 1 2
2
0 -3

从点 \((-10^8,-10^8)\) 沿直线 \(y=x\) 向上询问
设询问结果为ret
如果ret==0,那么将当前位置向右上平移1距离
否则将当前位置向右上平移ret距离
这样的话会 \(\text{TLE}\) 一个点,需要加一个剪枝
就是如果当前搜到一个点ret!=0,且这个点向上100距离搜到的点ret也!=0,那么直接向上跳100距离
好了

788 E

题意

\(n\) 个士兵,要选5个参加比赛
选的5个人合法的条件是:设这5个人的下标为 \(i,j,k,l,p\) ,满足 \(1\le i<j<k<l<p\le n\)\(a_i\le a_j = a_k = a_l ≥ a_p\)
现在有 \(m\) 次操作,每次操作规定某一个士兵不能作为 \(j,k,l\) 参加比赛或者能作为...参加比赛
对于每次操作,需要输出操作后选择5个人的方案数
\(10^9+7\)
\((1\le n,m\le 10^5,1\le a_i\le 10^9)\)

Examples

Input
6
1 1 1 1 1 1
2
1 3
2 3
Output
1
6
Input
8
3 4 4 2 4 5 4 1
3
1 5
2 5
1 2
Output
1
6
2

第一步:树状数组+离散化,维护 \(pre[i],nxt[i]\) ,分别表示 \(a[i]\) 前面的数中 \(\le a[i]\) 的有多少个, \(a[i]\) 后面的数中 \(\le a[i]\) 的有多少个。
第二步:线段树,对每个离散化的 \(a[i]\) 的值开一个线段树(动态开点),每个节点维护 \(6\) 个值: \(A,B,C,AB,BC,ABC\) ,表示当前节点所表示区间选出 j,k,l,j和k,k和l,j、k和l 的方案数。
具体操作:
先预处理出未进行任何操作时的答案。
叶子节点初始值:

t[p].A=pre[l];
t[p].B=1;
t[p].C=nxt[r];
t[p].AB=t[p].BC=t[p].ABC=0;

对于每次操作,对线段树进行单点修改。
对于每次操作后的询问,查询区间 \([1,n]\)

Code

#include<bits/stdc++.h>
#define maxn 200003
#define mod 1000000007
using namespace std;
int Plus(long long x,long long y){return (x+=y)>=mod?x%mod:x;}
int Minus(long long x,long long y){return (x+=mod-y)>=mod?x%mod:x;}
int mul(long long x,long long y){return (x*=y)>=mod?x%mod:x;}
int n,a[maxn],mp[maxn],cntmp,pre[maxn],nxt[maxn];
namespace BIT{
    int t[maxn];
    void clear(){
        for(int i=1;i<=n;i++)t[i]=0;
    }
    void add(int pos,int k){
        while(pos<=n){
            t[pos]+=k;
            pos+=pos&-pos;
        }
    }
    int query(int pos){
        int ret=0;
        while(pos){
            ret+=t[pos];
            pos-=pos&-pos;
        }
        return ret;
    }
}
namespace SEG{
    struct node{
        int _2,_3,_4,_23,_34,_234,son[2];
        node():_2(0),_3(0),_4(0),_23(0),_34(0),_234(0){son[0]=son[1]=0;}
    }t[maxn*20];
    int cnt,root[maxn];
    void pushup(int p){
        int son0=t[p].son[0],son1=t[p].son[1];
        t[p]._2=Plus(t[son0]._2,t[son1]._2);
        t[p]._3=Plus(t[son0]._3,t[son1]._3);
        t[p]._4=Plus(t[son0]._4,t[son1]._4);
        t[p]._23=Plus(mul(t[son0]._2,t[son1]._3),Plus(t[son0]._23,t[son1]._23));
        t[p]._34=Plus(mul(t[son0]._3,t[son1]._4),Plus(t[son0]._34,t[son1]._34));
        t[p]._234=Plus(Plus(Plus(mul(t[son0]._2,t[son1]._34),mul(t[son0]._23,t[son1]._4)),t[son0]._234),t[son1]._234);
    }
    void change(int& p,int l,int r,int pos,bool k){
        if(p==0)p=++cnt;
        if(l==r){
            t[p]._2=k*pre[pos];
            t[p]._3=k;
            t[p]._4=k*nxt[pos];
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)change(t[p].son[0],l,mid,pos,k);
        else change(t[p].son[1],mid+1,r,pos,k);
        pushup(p);
    }
    int query(int p){
        return t[p]._234;
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",a+i);
        mp[++cntmp]=a[i];
    }
    sort(mp+1,mp+cntmp+1);
    cntmp=unique(mp+1,mp+cntmp+1)-mp-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(mp+1,mp+cntmp+1,a[i])-mp;
    for(int i=1;i<=n;i++){
        pre[i]=BIT::query(a[i]);
        BIT::add(a[i],1);
    }
    BIT::clear();
    for(int i=n;i>=1;i--){
        nxt[i]=BIT::query(a[i]);
        BIT::add(a[i],1);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans=Minus(ans,SEG::query(SEG::root[a[i]]));
        SEG::change(SEG::root[a[i]],1,n,i,1);
        ans=Plus(ans,SEG::query(SEG::root[a[i]]));
    }
    int Q;
    scanf("%d",&Q);
    while(Q--){
        int mo,x;
        scanf("%d%d",&mo,&x);
        ans=Minus(ans,SEG::query(SEG::root[a[x]]));
        if(mo==1)SEG::change(SEG::root[a[x]],1,n,x,0);
        else SEG::change(SEG::root[a[x]],1,n,x,1);
        ans=Plus(ans,SEG::query(SEG::root[a[x]]));
        printf("%d\n",ans);
    }
    return 0;
}

Codeforces 788 (Div. 1)

标签:定义函数   input   不同   i++   long   bool   names   .so   tput   

原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10415222.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!