Educational Codeforces Round 56 Div. 2 翻车记

  A:签到。

View Code

  B:仅当只有一种字符时无法构成非回文串。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int T,n,cnt[26];
char s[N];
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    T=read();
    while (T--)
    {
        scanf("%s",s+1);n=strlen(s+1);
        memset(cnt,0,sizeof(cnt));
        for (int i=1;i<=n;i++) cnt[s[i]-'a']++;
        int tot=0;
        for (int i=0;i<26;i++) if (cnt[i]) tot++;
        if (tot==1) cout<<-1<<endl;
        else
        {
            for (int i=0;i<26;i++)
                for (int j=1;j<=cnt[i];j++)
                putchar(i+'a');
            cout<<endl;
        }
    }
    return 0;
}
View Code

  C:在满足条件的前提下使每对数的差尽量大。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
ll read()
{
    ll x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n;
ll a[N],b[N],l,r;
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    n=read();
    for (int i=1;i<=(n>>1);i++) a[i]=read();
    l=0,r=1000000000000000000;
    for (int i=1;i<=(n>>1);i++)
    {
        b[i]=l,b[n-i+1]=a[i]-l;
        if (b[n-i+1]>r) b[i]+=b[n-i+1]-r,b[n-i+1]=r;
        l=b[i],r=b[n-i+1];
    }
    for (int i=1;i<=n;i++) printf("%I64d ",b[i]);
    return 0;
}
View Code

  D:二分图染色,每个连通块贡献相乘即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
#define P 998244353
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
ll read()
{
    ll x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int T,n,m,t,p[N],color[N],white,black;
bool flag;
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k,int c)
{
    if (flag==0) return;
    color[k]=c;if (c==0) white++;else black++;
    for (int i=p[k];i;i=edge[i].nxt)
    {
        if (flag==0) return;
        if (color[edge[i].to]==-1) dfs(edge[i].to,c^1);
        else if (color[edge[i].to]==c) {flag=0;return;}
    }
}
int ksm(int a,int k)
{
    int s=1;
    for (;k;k>>=1,a=1ll*a*a%P)if (k&1) s=1ll*s*a%P;
    return s;
}
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    T=read();
    while (T--)
    {
        n=read(),m=read();flag=1;t=0;
        for (int i=1;i<=n;i++) p[i]=0,color[i]=-1;
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            addedge(x,y),addedge(y,x);
        }
        int cnt=0,ans=1;
        for (int i=1;i<=n;i++)
        if (color[i]==-1)
        {
            white=black=0,cnt++,dfs(i,0);
            ans=1ll*ans*(ksm(2,white)+ksm(2,black))%P;
        }
        if (flag==0) ans=0;
        printf("%d
",ans);
    }
    return 0;
}
View Code

  这都啥思博题啊20min切完。E一眼树状数组套个权值线段树,犹豫了一下ECR的E会不会这么毒瘤,最后还是码了。30min之后疯狂RE22,因为空间根本开不下。这时候才想起来带修改之后树状数组套个treap和它复杂度是一样的,还能回收下空间,于是又开始码码码,过了20min终于A掉了。

  E:将每个数在两个排列里的位置视为一个二维坐标。现在要做到就是插点/删点/矩形内点的个数。树状数组套treap即可,需要回收空间。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
using namespace std;
#define ll long long
#define N 200010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
ll read()
{
    ll x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,a[N],b[N],root[N],pos[N][2],q[N<<5],head,tail,t;
struct data{int ch[2],p,x,s;
}tree[N<<5];
int up(int k){tree[k].s=tree[lson].s+tree[rson].s+1;}
void move(int &k,int p)
{
    int t=tree[k].ch[p];
    tree[k].ch[p]=tree[t].ch[!p],tree[t].ch[!p]=k,up(k),up(t),k=t;
}
void INS(int &k,int x)
{
    if (k==0) {if (head<tail) k=q[++head];else k=++t;tree[k].ch[0]=tree[k].ch[1]=0;tree[k].x=x;tree[k].p=rand();tree[k].s=1;return;}
    tree[k].s++;
    if (tree[k].x<=x) {INS(rson,x);if (tree[rson].p>tree[k].p) move(k,1);}
    else {INS(lson,x);if (tree[lson].p>tree[k].p) move(k,0);}
}
void DEL(int &k,int x)
{
    if (tree[k].x==x)
    {
        if (lson==0||rson==0) {q[++tail]=k;k=lson|rson;return;}
        if (tree[lson].p>tree[rson].p) move(k,0),DEL(rson,x);
        else move(k,1),DEL(lson,x);
    }
    else if (tree[k].x<x) DEL(rson,x);
    else DEL(lson,x);
    up(k);
}
int find(int k,int x)
{
    if (!k) return 0;
    if (tree[k].x<=x) return tree[lson].s+1+find(rson,x);
    else return find(lson,x);
}
void ins(int k,int x)
{
    while (k<=n) INS(root[k],x),k+=k&-k;
}
void del(int k,int x)
{
    while (k<=n) DEL(root[k],x),k+=k&-k;
}
int query(int k,int x) 
{
    int ans=0;
    while (k) ans+=find(root[k],x),k-=k&-k;
    return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    n=read(),m=read();
    srand(time(0));
    for (int i=1;i<=n;i++) a[i]=read(),pos[a[i]][0]=i;
    for (int i=1;i<=n;i++) b[i]=read(),pos[b[i]][1]=i;
    for (int i=1;i<=n;i++) ins(i,pos[a[i]][1]);
    for (int i=1;i<=m;i++)
    {
        int op=read();
        if (op==1)
        {
            int la=read(),ra=read(),lb=read(),rb=read();
            printf("%d
",query(ra,rb)-query(ra,lb-1)-query(la-1,rb)+query(la-1,lb-1));
        }
        else
        {
            int x=read(),y=read();
            del(pos[b[x]][0],x),del(pos[b[y]][0],y),
            ins(pos[b[x]][0],y),ins(pos[b[y]][0],x);
            swap(b[x],b[y]);
        }
    }
    return 0;
}
View Code

  G:将两点间曼哈顿距离的绝对值展开讨论,可以发现对于每种情况,两点每维坐标的贡献与其原来该维坐标的关系都是相同的(即正或负),于是线段树暴力维护2k种状态即可。我也不知道为什么两个树套树我只写了50min(bit套树根本就没什么码量吧),一个裸的线段树我能写40min。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
using namespace std;
#define ll long long
#define N 200010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,k,a[N][5];
struct data{int l,r,f[32],g[32];
}tree[N<<2];
void dfs(int node,int x,int p,int s,int sum)
{
    if (p==k) {tree[node].f[sum]=tree[node].g[sum]=s;return;}
    dfs(node,x,p+1,s-a[x][p],sum);
    dfs(node,x,p+1,s+a[x][p],sum|(1<<p));
}
data merge(data x,data y)
{
    data u;u.l=x.l,u.r=y.r;
    for (int i=0;i<(1<<k);i++)
    u.f[i]=max(x.f[i],y.f[i]),u.g[i]=min(x.g[i],y.g[i]);
    return u;
}
void build(int k,int l,int r)
{
    tree[k].l=l,tree[k].r=r;
    if (l==r) {dfs(k,l,0,0,0);return;}
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tree[k]=merge(tree[k<<1],tree[k<<1|1]);
}
void modify(int k,int x)
{
    if (tree[k].l==tree[k].r) {dfs(k,x,0,0,0);return;}
    int mid=tree[k].l+tree[k].r>>1;
    if (x<=mid) modify(k<<1,x);
    else modify(k<<1|1,x);
    tree[k]=merge(tree[k<<1],tree[k<<1|1]);
}
data query(int k,int l,int r)
{
    if (tree[k].l==l&&tree[k].r==r) return tree[k];
    int mid=tree[k].l+tree[k].r>>1;
    if (r<=mid) return query(k<<1,l,r);
    else if (l>mid) return query(k<<1|1,l,r);
    else return merge(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
}
int main()
{
    n=read(),k=read();
    for (int i=1;i<=n;i++)
        for (int j=0;j<k;j++)
        a[i][j]=read();
    build(1,1,n);
    m=read();
    for (int i=1;i<=m;i++)
    {
        int op=read();
        if (op==1)
        {
            int x=read();
            for (int j=0;j<k;j++) a[x][j]=read();
            modify(1,x);
        }
        else
        {
            int l=read(),r=read();
            data x=query(1,l,r);
            int ans=0;
            for (int i=0;i<(1<<k);i++)
            ans=max(ans,x.f[i]-x.g[i]);
            printf("%d
",ans);
        }
    }
}
View Code

  F:没看。

  突然小号也变得橘里橘气。result:rank 10 rating +170

原文地址:https://www.cnblogs.com/Gloid/p/10125536.html