1. 程式人生 > >Codeforces Educational round 58

Codeforces Educational round 58

mes code its Education puts esp 單調隊列 space 一個

Ediv2 58

  • 隨手AK.jpg

D

裸的虛樹,在這裏就不寫了

E

傻逼貪心?這個題過的比$B$都多.jpg

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 500005
#define ll long long
int n,now_mx,maxx;char s[10];
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        int x,y;scanf("%s%d%d",s+1,&x,&y);
        if(x<y)swap(x,y);
        if(s[1]=='+')now_mx=max(x,now_mx),maxx=max(y,maxx);
        else puts(x>=now_mx&&y>=maxx?"YES":"NO");
    }
}

F

似乎正解的那個單調隊列做法沒啥意思啊...

直接暴力二分+剪枝就好了...

然後其實能卡掉,但是懶得去卡了.jpg

然後卡一卡常數就好了.jpg

隨便剪一剪枝前測就能過.jpg

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 405
#define ll long long
int a[N],n,m,s,t,f,c,l,r;ll ans;
inline bool check(int x)
{
    register int i,tc=c;register int now=x;
    for(i=s;i<t;i++)
    {
        if(a[i+1]-a[i]>x)return 0;
        if(a[i+1]-a[i]>now)
        {
            if(!tc)return 0;
            tc--;now=x;
        }
        now-=a[i+1]-a[i];
    }return 1;
}
int main()
{
    scanf("%d%d",&n,&m);l=0,r=1<<30;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    while(m--)
    {
        scanf("%d%d%d%d",&s,&t,&f,&c);if(s>t)swap(s,t);
        if(check(ans/f))continue;
        l=(ans/f)+1;r=a[t]-a[s];
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(check(mid))r=mid;else l=mid+1;
        }ans=max((ll)l*f,ans);
    }
    printf("%lld\n",ans);
}

G

一個結論,能劃分出的段數是線性基裏的基的個數

證明嘛:

對於任意一個已經存在的基,都可以被一些數表達出來

然後就可以發現,不可能存在一個劃分的段數比線性基裏的基數更多(根據線性基的定義

然後就完了.jpg

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 200005
#define ll long long
int a[32],now;
void insert(int x)
{
    for(int i=30;~i;i--)if((x>>i)&1)
        if(a[i])x^=a[i];
        else {a[i]=x;return ;}
}
int main()
{
    int n,x;
    scanf("%d",&n);
    while(n--)scanf("%d",&x),insert(x),now^=x;
    if(!now)return puts("-1"),0;
    x=0;
    for(int i=30;~i;i--)if(a[i])x++;
    printf("%d\n",x);
}

Codeforces Educational round 58