Educational Codeforces Round 62

A

模拟......

#include<cstdio>
#include<algorithm>
using namespace std;
int a[10005],n,ans;
int main(){
    scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    int i=1;
    while(i<=n){
        int now=a[i],j=i;ans++;
        while(j<n&&now>j) j++,now=max(now,a[j]);
        i=j+1;
    }
    printf("%d\n",ans);return 0;
} 

B

考虑保留前端的\(>\),后端的\(<\)的最优解即可.

#include<cstdio>
#include<algorithm>
using namespace std;
int n,T,ans;
char s[105];
void work(){
    scanf("%d",&n);scanf("%s",s+1);ans=n;
    int i=1;while(i<=n&&s[i]!='>') i++;ans=min(ans,i-1);
    //printf("%d\n",i);
    i=n;while(i>=1&&s[i]!='<') i--;ans=min(ans,n-i);//printf("%d\n",i);
    printf("%d\n",ans);
}
int main(){
    scanf("%d",&T);while(T--) work();
    return 0;
} 

C

排序后用堆维护前K大.

#include<cstdio>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=300005;
int n,K;
struct jz{
    int x,y;
    bool operator<(const jz &b)const{return y>b.y;}
}a[maxn];
int top;
LL ans,num;
priority_queue<int,vector<int>,greater<int> >heap;
void put(int x){num+=x;top++;heap.push(x);}
void get(){top--;num-=heap.top();heap.pop();}
int main(){
    scanf("%d%d",&n,&K);
    for (int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
    sort(a+1,a+1+n);
    for (int i=1;i<=n;i++){
        put(a[i].x);
        if (top>K) get();
        ans=max(ans,num*a[i].y);
    }
    printf("%lld\n",ans);
    return 0;
} 

D

每次都是从\(1\)开始相邻两个剖分显然是最优解.

#include<cstdio>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=300005;
int n,K;
LL ans,num;
int main(){
    scanf("%d%d",&n);
    for (int i=3;i<=n;i++) ans+=(i-1)*i;
    printf("%lld\n",ans);
    return 0;
} 

E

显然只要满足\(a[i]!=a[i-2]\)即可.按位置奇偶分开考虑,那么就是相邻的数不相同.

考虑暴力的DP,\(f[i][j]\)做完前\(i\)个位置第\(i\)个位置的数是\(j\),转移显然.

然后发现转移的时候类似一个区间乘区间加的操作,直接线段树维护即可.

好像与题解有所不同,因为乘法的时候有负数,所以被坑了...

#include<queue>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=200005,tt=998244353;
int n,c[maxn],K;
struct jz{
    int L,R;
    LL tag1,tag2,w;
}a[4*maxn];
LL ans;
void build(int x,int L,int R){
    a[x].L=L;a[x].R=R;a[x].tag1=1;a[x].tag2=0;
    if (L==R){a[x].w=0;return;}
    int mid=L+R>>1;
    build(x*2,L,mid);build(x*2+1,mid+1,R);
    a[x].w=(a[x*2].w+a[x*2+1].w)%tt;
}
void Pushdown(int x){
    if (a[x].L==a[x].R) return;
    LL tag1=a[x].tag1,tag2=a[x].tag2;a[x].tag1=1;a[x].tag2=0;
    a[x*2].w=(a[x*2].w*tag1+tag2*(a[x*2].R-a[x*2].L+1))%tt;
    a[x*2+1].w=(a[x*2+1].w*tag1+tag2*(a[x*2+1].R-a[x*2+1].L+1))%tt;
    a[x*2].tag1=(a[x*2].tag1*tag1)%tt;
    a[x*2+1].tag1=(a[x*2+1].tag1*tag1)%tt;
    a[x*2].tag2=(a[x*2].tag2*tag1+tag2)%tt;
    a[x*2+1].tag2=(a[x*2+1].tag2*tag1+tag2)%tt;
}
void change(int x,int L,int R,int c,int p){
    Pushdown(x);
    if (a[x].L==L&&a[x].R==R){
        a[x].tag1=(a[x].tag1*c)%tt;
        a[x].tag2=(a[x].tag2*c%tt+p)%tt;
        a[x].w=(a[x].w*c%tt+(LL)(a[x].R-a[x].L+1)*p)%tt;
        return;
    }
    int mid=a[x].L+a[x].R>>1;
    if (R<=mid) change(x*2,L,R,c,p);
    else if (L>mid) change(x*2+1,L,R,c,p);
    else{change(x*2,L,mid,c,p);change(x*2+1,mid+1,R,c,p);}
    a[x].w=(a[x*2].w+a[x*2+1].w)%tt;
}
int query(int x,int L,int R){
    Pushdown(x);
    if (a[x].L==L&&a[x].R==R) return (a[x].w+tt)%tt;
    int mid=a[x].L+a[x].R>>1;
    if (R<=mid) return query(x*2,L,R);
    else if (L>mid) return query(x*2+1,L,R);
    else return (query(x*2,L,mid)+query(x*2+1,mid+1,R))%tt;
}
int main(){
    scanf("%d%d",&n,&K);
    for (int i=1;i<=n;i++) scanf("%d",&c[i]);ans=1;
    build(1,1,K);
    if (c[1]!=-1) change(1,c[1],c[1],1,1);else change(1,1,K,1,1);
    for (int i=3;i<=n;i+=2){
        int sum=query(1,1,K);
        if (c[i]!=-1){
            if (c[i]>1) change(1,1,c[i]-1,0,0);
            if (c[i]<K) change(1,c[i]+1,K,0,0);
            change(1,c[i],c[i],-1,sum);
        }else change(1,1,K,-1,sum);
    }
    ans=ans*query(1,1,K)%tt;
    build(1,1,K);
    if (c[2]!=-1) change(1,c[2],c[2],1,1);else change(1,1,K,1,1);
    for (int i=4;i<=n;i+=2){
        int sum=query(1,1,K);
        if (c[i]!=-1){
            if (c[i]>1) change(1,1,c[i]-1,0,0);
            if (c[i]<K) change(1,c[i]+1,K,0,0);
            change(1,c[i],c[i],-1,sum);
        }else change(1,1,K,-1,sum);
    }
    ans=ans*query(1,1,K)%tt;
    printf("%lld\n",ans);
    return 0;
} 

F

感觉比较显然...

把行和列看成点,加入/删除点就是加入/删除一条边,最后答案显然就是所有联通中行数*列数的和.

直接线段树分治+并查集维护就可以了.

#include<map>
#include<cstdio>
#include<vector>
#include<algorithm>
#define LL long long
#define ls (x<<1)
#define rs ((x<<1)+1)
using namespace std;
const int maxn=600005,N=3e5;
struct jz{int x,y,d;}a[maxn];
struct node{
    int x,y;
    node(int x=0,int y=0):x(x),y(y){}
}S[maxn];
map<LL,int> vis;
vector<int> que[maxn*4];
int n,top,f[maxn],sx[maxn],sy[maxn];
LL ans;
inline int _read(){
    int num=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') num=num*10+ch-48,ch=getchar();
    return num;
}
void add(int x,int l,int r,int L,int R,int y){
    if (l==L&&r==R){que[x].push_back(y);return;}
    int mid=l+(r-l>>1);
    if (R<=mid) add(ls,l,mid,L,R,y);else
    if (L>mid) add(rs,mid+1,r,L,R,y);else
    add(ls,l,mid,L,mid,y),add(rs,mid+1,r,mid+1,R,y);
}
int get(int x){if (f[x]==x) return x;return get(f[x]);}
void add(int x,int w){ans+=(LL)sx[x]*sy[x]*w;}
void merge(int x,int y){
    x=get(x);y=get(y);if (x==y) return;
    if (sx[x]+sy[x]<sx[y]+sy[y]) swap(x,y);
    S[++top]=node(x,y);add(x,-1);add(y,-1);
    f[y]=x;sx[x]+=sx[y];sy[x]+=sy[y];add(x,1);
}
void Back(int x){
    while(top!=x){
        int x=S[top].x,y=S[top].y;add(x,-1);
        f[y]=y;sx[x]-=sx[y];sy[x]-=sy[y];add(x,1);add(y,1);top--;
    }
}
void work(int x,int l,int r){
    int tim=top;
    for (int i=0;i<que[x].size();i++) merge(a[que[x][i]].x,a[que[x][i]].y+N);
    if (l==r){
        printf("%lld ",ans);
        if (a[l+1].d) add(1,1,n,l+1,a[l+1].d,l+1); 
        Back(tim);return;
    }int mid=l+(r-l>>1);
    work(ls,l,mid);work(rs,mid+1,r);Back(tim);
}
int main(){
    n=_read();for (int i=1;i<=n;i++){
        a[i].x=_read(),a[i].y=_read();
        LL w=(LL)a[i].x*N+a[i].y;
        if (!vis[w]) vis[w]=i;else a[vis[w]].d=i-1,vis[w]=0;
    }
    for (int i=n;i>=1;i--){
        LL w=(LL)a[i].x*N+a[i].y;
        if (vis[w]) a[i].d=n,vis[w]=0;
    }
    for (int i=1;i<=2*N;i++) f[i]=i,sx[i]=(i<=N),sy[i]=(i>N);
    //for (int i=1;i<=n;i++) printf("%d\n",a[i].d);
    if (a[1].d) add(1,1,n,1,a[1].d,1);work(1,1,n);
    return 0;
}

G

咕咕咕...

猜你喜欢

转载自www.cnblogs.com/CHNJZ/p/10635548.html