1. 程式人生 > >Educational Codeforces Round 56 Div. 2 翻車記

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\n",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\n",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\n",ans);
        }
    }
}
View Code

  F:沒看。

  坐等fst。