Codeforces Round #567 (Div. 2)自闭记

嘿嘿嘿,第一篇文章,感觉代码可以缩起来简直不要太爽

打个div2发挥都这么差...

平均一题fail一次,还调不出错,自闭了

又一次跳A开B,又一次B傻逼错误调不出来

罚时上天,E还傻逼了..本来这场应该很前的,最后只苟在rated的人里面50

A. Chunga-Changa

随便做就行了,因为CF似乎不可以print("%d",0);于是WA了一个样例

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;

int main()
{
    LL x,y,z;
    scanf("%lld%lld%lld",&x,&y,&z);
    if (x/z+y/z==(x+y)/z) printf("%lld 0\n",(x+y)/z);
    else 
    {
        LL t=(z-y%z)%z;
        LL t1=(z-x%z)%z;
        LL ans=0;
        printf("%lld %lld\n",(x+y)/z,min(t,t1));
    }
    return 0;
}
View Code

B. Split a Number

显然取中间最优,但可能中间有0,那就往两边找

然后一开始有一个大于号写成小于号WA了一发,然后看了半天看不出,最后使得A和B都是30min过

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const int N=100005;
char ss[N];
int n;
int cnt;
bool tf=false;
int len,a[N];
int b[N],len1;
bool JD ()
{
    if (tf==false) return true;
    if (len<len1) return false;
    if (len>len1) return true;
    for (int u=1;u<=len;u++) 
    {
        if (a[u]<b[u]) return false;
        if (a[u]>b[u]) return true;
    }
    return true;
}
void check (int x)
{
    if (ss[x+1]=='0') return ;
    cnt++;
    len1=max(x,n-x);
    memset(b,0,sizeof(b));
    int i=x,j=n;
    for (int u=len1;u>=1;u--)
    {
        if (i>=1) b[u]=b[u]+ss[i]-'0';
        if (j>x) b[u]=b[u]+ss[j]-'0';
        i--;j--;
    }
    for (int u=len1;u>=1;u--) b[u-1]=b[u-1]+b[u]/10,b[u]%=10;
    if (b[0]!=0)
    {
        len1++;
        for (int u=len1;u>=1;u--) b[u]=b[u-1];
    }
    if (JD())
    {
        len=len1;tf=true;
        for (int u=1;u<=len;u++) a[u]=b[u];
    }
}
int main()
{
    scanf("%d",&n);scanf("%s",ss+1);
    cnt=0;
    for (int u=n/2;u>=1;u--)
    {
        check(u);
        if (cnt>=50) break;
    }
    cnt=0;
    for (int u=n/2;u<n;u++)
    {
        check(u);
        if (cnt>=50) break;
    }
    for (int u=1;u<=len;u++) printf("%d",a[u]);
    return 0;
}
View Code

C. Flag

考虑枚举左上角,那么我们要知道的就是每个点往下多少个就不同D以及在这一段里面往右多少个就不同R

贡献就是三段R的min

前两段的D要一样,问题是第三段他只要比前两段的D大就好了

于是再倒着维护一个U,然后第三段跳到左下角查询,复杂度O(nm)

然后一个变量打错了,WA了两发

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const int N=1005;
char ss[N][N];
int n,m;
int R[N][N];
int mn[N][N];
int D[N][N];
int mn1[N][N];
int main()
{
    scanf("%d%d",&n,&m);
    for (int u=1;u<=n;u++) scanf("%s",ss[u]+1);
    for (int u=n;u>=1;u--)
    {
        for (int i=m;i>=1;i--)
        {
            if (ss[u][i]==ss[u][i+1]) R[u][i]=R[u][i+1]+1;
            else R[u][i]=1;
        }
    }
    for (int u=1;u<=n;u++)
    for (int i=1;i<=m;i++)
    {
        mn1[u][i]=R[u][i];
        if (ss[u][i]==ss[u-1][i]) mn1[u][i]=min(mn1[u][i],mn1[u-1][i]);
    }
    for (int u=n;u>=1;u--)
    for (int i=1;i<=m;i++)
    {
        mn[u][i]=R[u][i];
        if (ss[u][i]==ss[u+1][i]) 
        {
            mn[u][i]=min(mn[u][i],mn[u+1][i]);
            D[u][i]=D[u+1][i]+1;
        }
        else D[u][i]=1;
    }
    int ans=0;
    for (int u=1;u<=n;u++)
    for (int i=1;i<=m;i++)
    {
        int x1,x2,x3;
        x1=u;
        x2=x1+D[x1][i];
        x3=x2+D[x2][i];
        if (D[x1][i]!=D[x2][i]) continue;
        if (D[x3][i]<D[x2][i]) continue;
        x3=x3+D[x2][i]-1;
        if (x3>n) continue;
        ans=ans+min(min(mn[x1][i],mn[x2][i]),mn1[x3][i]);
        //printf("%d %d %d %d %d\n",u,i,x1,x2,x3);
    }
    printf("%d\n",ans);
    return 0;
}
View Code

D. Irrigation

模拟这个过程使得所有人一样

每一次把所有i的人变为i+1

发现要维护现在又多少人,以及第k大

开个线段树就好了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const LL N=500005;
LL n,m,Q;
LL a[N];
struct qt
{
    LL l,r;
    LL c;
    LL s1,s2;
}tr[N*2];LL num;
void bt (LL l,LL r)
{
    LL now=++num;
    tr[now].l=l;tr[now].r=r;tr[now].c=0;
    if (l==r) return ;
    LL mid=(l+r)>>1;
    tr[now].s1=num+1;bt(l,mid);
    tr[now].s2=num+1;bt(mid+1,r);
}
LL query (LL now,LL x)
{
    if (tr[now].l==tr[now].r) return tr[now].l;
    LL mid=(tr[now].l+tr[now].r)>>1;
    LL s1=tr[now].s1,s2=tr[now].s2;
    if (tr[s1].c>=x) return query(s1,x);
    else return query(s2,x-tr[s1].c);
}
void add (LL now,LL c)
{
    tr[now].c++;
    if (tr[now].l==tr[now].r) return ;
    LL mid=(tr[now].l+tr[now].r)>>1;
    LL s1=tr[now].s1,s2=tr[now].s2;
    if (c<=mid) add(s1,c);
    else add(s2,c);
}
vector<LL> vec[N];
LL ans[N];
struct qq
{
    LL x,id;
}q[N];
bool cmp (qq x,qq y) {return x.x<y.x;}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&Q);
    for (LL u=1;u<=n;u++)    {LL x;scanf("%lld",&x);a[x]++;}
    bt(1,m);
    for (LL u=1;u<=m;u++) vec[a[u]].push_back(u);
    for (LL u=1;u<=Q;u++)    {scanf("%lld",&q[u].x);q[u].x-=n;q[u].id=u;}
    sort(q+1,q+1+Q,cmp);
    LL now=0,now1=1;//�ٰ��˶�������
    for (LL u=0;u<=n;u++)
    {
        while (now1<=Q&&now+tr[1].c>=q[now1].x)    {ans[q[now1].id]=query(1,q[now1].x-now);now1++;}
        now=now+tr[1].c;
        LL siz=vec[u].size();
        for (LL i=0;i<siz;i++) add(1,vec[u][i]);
    }
    while (now1<=Q)
    {
        LL t=q[now1].x-now;
        t=t%m;if (t==0) t=m;
        ans[q[now1].id]=t;
        now1++;
    }
    for (LL u=1;u<=Q;u++) printf("%lld\n",ans[u]);
    return 0;
}
View Code

E1. A Story of One Country (Easy)

打的时候有点崩,不好意思说自己写了个什么傻吊玩意了

就是暴力枚举一个能切的地方就好了,递归处理,复杂度是O(n^2)的

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const int N=1005;
const int MAX=1e9;
struct qq
{
    int x1,y1,x2,y2;
    qq () {}
    qq (int a,int b,int c,int d)    {x1=a;y1=b;x2=c;y2=d;}
};
bool cmp (qq x,qq y)    {return x.x1<y.x1;}
bool cmp1 (qq x,qq y)    {return x.y1<y.y1;}
int n;
bool solve (vector<qq> vec)
{
    int siz=vec.size();    
    if (siz==1) return true;
    vector<qq> a,b;a.clear();b.clear();
    sort(vec.begin(),vec.end(),cmp);
    for (int u=siz-1;u>=0;u--) b.push_back(vec[u]);
    int mx=0;
    for (int u=0;u<siz;u++)
    {
        b.pop_back();a.push_back(vec[u]);mx=max(mx,a[u].x2);
        if (u!=siz-1&&mx<=vec[u+1].x1)    
        {
            //printf("%d %d\n",siz,u);
            return solve(a)&solve(b);
        }
    }
    sort(vec.begin(),vec.end(),cmp1);
    a.clear();b.clear();
    for (int u=siz-1;u>=0;u--) b.push_back(vec[u]);
    mx=0;
    for (int u=0;u<siz;u++)
    {
        b.pop_back();a.push_back(vec[u]);mx=max(mx,a[u].y2);
        if (u!=siz-1&&mx<=vec[u+1].y1)    return solve(a)&solve(b);
    }
    return false;
}
int main()
{
    scanf("%d",&n);
    vector<qq> vec;
    for (int u=1;u<=n;u++)
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        vec.push_back(qq(a,b,c,d));
    }
    if (solve(vec)) printf("YES\n");
    else printf("NO\n");
    return 0;
}
View Code

E2. A Story of One Country (Hard)

考虑优化上面这个过程,其实只需要四个方向一起枚举就可以了

枚举到最小的一个就递归下去,复杂度是启发式分裂,也就是和启发式合并一样的复杂度nlogn

但是实现有点小技巧,因为你不可以扫全部元素,否则复杂度就退化了

那么就是要维护一个有序序列,还要支持删除,显然维护4个set就行了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
const int MAX=1e9;
struct qq
{
    int x1,y1,x2,y2;
    qq () {}
    qq (int a,int b,int c,int d)    {x1=a;y1=b;x2=c;y2=d;}
};
struct cmp1
{
    inline bool operator () (qq a,qq b)    {return a.x1==b.x1?a.y1<b.y1:a.x1<b.x1;}
};
struct cmp2
{
    inline bool operator () (qq a,qq b)    {return a.y1==b.y1?a.x1<b.x1:a.y1<b.y1;}
};
struct cmp3
{
    inline bool operator () (qq a,qq b)    {return a.x2==b.x2?a.y2<b.y2:a.x2>b.x2;}
};
struct cmp4
{
    inline bool operator () (qq a,qq b)    {return a.y2==b.y2?a.x2<b.x2:a.y2>b.y2;}
};
int n;
bool solve (set<qq,cmp1> &s1,set<qq,cmp2> &s2,set<qq,cmp3> &s3,set<qq,cmp4> &s4)
{
    int siz=s1.size();    
    if (siz==1) 
    {
        s1.clear();s2.clear();s3.clear();s4.clear();
        return true;
    }

    set<qq,cmp1> g1;g1.clear();set<qq,cmp1> :: iterator it1=s1.begin();
    set<qq,cmp2> g2;g2.clear();set<qq,cmp2> :: iterator it2=s2.begin();
    set<qq,cmp3> g3;g3.clear();set<qq,cmp3> :: iterator it3=s3.begin();
    set<qq,cmp4> g4;g4.clear();set<qq,cmp4> :: iterator it4=s4.begin();
    
    int mxx=0,mxy=0,mnx=MAX,mny=MAX;
    for (int u=0;u<siz-1;u++)
    {
        mxx=max(mxx,(*it1).x2);it1++;
        if (mxx<=(*it1).x1)
        {
            set<qq,cmp1> :: iterator now=s1.begin();
            while (now!=it1)
            {
                qq xx=(*now);now++;
                s1.erase(xx);g1.insert(xx);
                s2.erase(xx);g2.insert(xx);
                s3.erase(xx);g3.insert(xx);
                s4.erase(xx);g4.insert(xx);
            }
            return solve(g1,g2,g3,g4)&solve(s1,s2,s3,s4);
        }
        mxy=max(mxy,(*it2).y2);it2++;
        
        if (mxy<=(*it2).y1)
        {
            set<qq,cmp2> :: iterator now=s2.begin();
            while (now!=it2)
            {
                qq xx=(*now);now++;
                s1.erase(xx);g1.insert(xx);
                s2.erase(xx);g2.insert(xx);
                s3.erase(xx);g3.insert(xx);
                s4.erase(xx);g4.insert(xx);
            }
            return solve(g1,g2,g3,g4)&solve(s1,s2,s3,s4);
        }
        mnx=min(mnx,(*it3).x1);it3++;
        if (mnx>=(*it3).x2)
        {
            set<qq,cmp3> :: iterator now=s3.begin();
            while (now!=it3)
            {
                qq xx=(*now);now++;
                s1.erase(xx);g1.insert(xx);
                s2.erase(xx);g2.insert(xx);
                s3.erase(xx);g3.insert(xx);
                s4.erase(xx);g4.insert(xx);
            }
            return solve(g1,g2,g3,g4)&solve(s1,s2,s3,s4);
        }
        mny=min(mny,(*it4).y1);it4++;
        if (mny>=(*it4).y2)
        {
            set<qq,cmp4> :: iterator now=s4.begin();
            while (now!=it4)
            {
                qq xx=(*now);now++;
                s1.erase(xx);g1.insert(xx);
                s2.erase(xx);g2.insert(xx);
                s3.erase(xx);g3.insert(xx);
                s4.erase(xx);g4.insert(xx);
            }
            return solve(g1,g2,g3,g4)&solve(s1,s2,s3,s4);
        }
    }
    return false;
}
int main()
{
    scanf("%d",&n);
    set<qq,cmp1> s1;
    set<qq,cmp2> s2;
    set<qq,cmp3> s3;
    set<qq,cmp4> s4;
    for (int u=1;u<=n;u++)
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        s1.insert(qq(a,b,c,d));
        s2.insert(qq(a,b,c,d));
        s3.insert(qq(a,b,c,d));
        s4.insert(qq(a,b,c,d));
    }
    if (solve(s1,s2,s3,s4)) printf("YES\n");
    else printf("NO\n");
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Als123/p/11037265.html