Educational Codeforces Round 22

Problems
 
 
#Name  
A
standard input/output
2 s, 256 MB
Submit Add to favourites  x1629
B
standard input/output
1 s, 256 MB
Submit Add to favourites  x506
C
standard input/output
1 s, 256 MB
Submit Add to favourites  x656
D
standard input/output
2 s, 256 MB
Submit Add to favourites  x21
E
standard input/output
2 s, 256 MB
Submit Add to favourites  x92
F
standard input/output
6 s, 256 MB
Submit Add to favourites  x25

A

水题 不解释

#include <bits/stdc++.h>
using namespace std;
int n,m,xx,yy,sum;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&xx),sum+=xx;
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&xx,&yy);
        if(xx<=sum&&yy>=sum){printf("%d\n",sum);return 0;}
        else if(sum<xx){printf("%d\n",xx);return 0;}
    }puts("-1");
}

B

这题全是细节

要判有没有爆long long还有边界情况

#include <bits/stdc++.h>
using namespace std;
#define int long long
int x,y,l,r,ans;
set<int>s;
bool check(int x,int y){return log10(x)+log10(y)>18;}
signed main(){
    scanf("%I64d%I64d%I64d%I64d",&x,&y,&l,&r);
    for(int i=0,t=1;;i++,t=t*x){
        if(t>r)break;
        for(int j=0,w=1;;j++,w=w*y){
            if(t+w>r)break;
            if(t+w>=l)s.insert(t+w);
            if(check(w,y))break;
        }
        if(check(t,x))break;
    }
    if(s.empty()){printf("%I64d\n",r-l+1);return 0;}
    ans=max(*s.begin()-l,0ll);
    for(set<int>::iterator it=s.begin(),it2;it!=s.end();it++){
        it2=it;
        if(it!=s.begin())it2--;
        ans=max(ans,*it-*it2-1);
        it2=it,it2++;
        if(it2==s.end())ans=max(ans,r-*it);
    }printf("%I64d\n",ans);
}

C

贪心

在不被追到的情况下走的最远

一遍DFS即可  (为什么题解全是2遍dfs的  难以理解)

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=400050;
int n,x,first[N],nxt[N],v[N],tot,deep[N],xx,yy,rec[N],fa[N],ans;
void add(int x,int y){v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}
void dfs(int x){
    for(int i=first[x];~i;i=nxt[i])if(v[i]!=fa[x])
        fa[v[i]]=x,deep[v[i]]=deep[x]+1,dfs(v[i]),rec[x]=max(rec[x],rec[v[i]]+1);
}
int main(){
    memset(first,-1,sizeof(first));
    scanf("%d%d",&n,&x);
    for(int i=1;i<n;i++)scanf("%d%d",&xx,&yy),add(xx,yy),add(yy,xx);
    deep[1]=1,dfs(1);
    ans=max(ans,(deep[x]-1+rec[x])*2);
    for(int i=x,t=0;;i=fa[i],t++){
        if(deep[x]-t*2<2)break;
        ans=max(ans,(deep[i]-1)*2+rec[i]*2);
    }printf("%d\n",ans);
}

D

DP

f[i][j] A选a[i] B选[j]的最长长度

维护两个数组 X[i]表示mod 7 为i的最长长度

Y[i]表示数字是i的最长长度

为了去重

只从i<j转移   更新i>j的情况

            if(i<j)ans=max(ans,f[j][i]=f[i][j]=max(max(Y[a[j]+1],max(Y[a[j]-1],X[a[j]%7])),f[i][0])+1);
            X[a[j]%7]=max(X[a[j]%7],f[i][j]),Y[a[j]]=max(Y[a[j]],f[i][j]);
//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=5050;
int f[N][N],a[N],n,X[7],Y[100500],ans;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=0;i<=n;i++){
        memset(X,0,sizeof(X)),memset(Y,0,sizeof(Y));
        for(int j=1;j<=n;j++){
            if(i==j)continue;
            if(i<j)ans=max(ans,f[j][i]=f[i][j]=max(max(Y[a[j]+1],max(Y[a[j]-1],X[a[j]%7])),f[i][0])+1);
            X[a[j]%7]=max(X[a[j]%7],f[i][j]),Y[a[j]]=max(Y[a[j]],f[i][j]);
        }
    }
    printf("%d\n",ans);
}

E

一个点有没有被算到答案里  

只跟它k次之前出现的地方有没有小于l有关

那  主席树直接上

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=100050;
vector<int>vec[N];
int n,k,q,xx,yy,a[N],jy,s[N],lson[N*66],rson[N*66],tree[N*66],cnt,root[N],lst;
void insert(int l,int r,int &pos,int last,int wei){
    pos=++cnt;tree[pos]=tree[last]+1;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(mid<wei)lson[pos]=lson[last],insert(mid+1,r,rson[pos],rson[last],wei);
    else rson[pos]=rson[last],insert(l,mid,lson[pos],lson[last],wei);
}
int query(int l,int r,int pos,int last,int L,int R){
    if(l>=L&&r<=R)return tree[pos]-tree[last];
    int mid=(l+r)>>1;
    if(mid<L)return query(mid+1,r,rson[pos],rson[last],L,R);
    else if(mid>=R)return query(l,mid,lson[pos],lson[last],L,R);
    else return query(l,mid,lson[pos],lson[last],L,R)+query(mid+1,r,rson[pos],rson[last],L,R);
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        vec[a[i]].push_back(i),jy=vec[a[i]].size()-1;
        s[i]=jy>=k?vec[a[i]][jy-k]:0,insert(0,N,root[i],root[i-1],s[i]);
    }
    scanf("%d",&q);
    while(q--){
        scanf("%d%d",&xx,&yy),xx=(xx+lst)%n+1,yy=(yy+lst)%n+1;
        if(xx>yy)swap(xx,yy);
        printf("%d\n",lst=query(0,N,root[yy],root[xx-1],0,xx-1));
    }
}

F

BZOJ 4025

并查集+cdq分治

我打的是线段树+vector

最后DFS一遍

效果一样

 

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=100050;
int n,q,f[N],top,size[N],dis[N];
struct Edge{int from,to,tim;Edge(){}Edge(int x,int y){from=x,to=y;}}edge[N];
struct Update{int fx,fy,disx;Update(){}Update(int x,int y,int z){fx=x,fy=y,disx=z;}}upd[N];
bool operator<(Edge a,Edge b){if(a.from!=b.from)return a.from<b.from;return a.to<b.to;}
set<Edge>st;set<Edge>::iterator it;vector<Edge>vec[N*8];
void insert(int l,int r,int pos,int L,int R,Edge t){
    if(l>=L&&r<=R){vec[pos].push_back(t);return;}
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<L)insert(mid+1,r,rson,L,R,t);
    else if(mid>=R)insert(l,mid,lson,L,R,t);
    else insert(l,mid,lson,L,R,t),insert(mid+1,r,rson,L,R,t);
}
int find(int x){return x==f[x]?x:find(f[x]);}
void merge(int x,int y,int z){
    if(size[x]>size[y])swap(x,y);
    upd[++top]=Update(x,y,dis[x]);
    f[x]=y,dis[x]=z,size[y]+=size[x];
}
bool get_dis(int x){
    int r=0;
    while(f[x]!=x)r^=dis[x],x=f[x];
    return r;
}
void query(int l,int r,int pos){
    int rec=top;
    for(int i=0;i<vec[pos].size();i++){
        int x=find(vec[pos][i].from),y=find(vec[pos][i].to),z=get_dis(vec[pos][i].from)^get_dis(vec[pos][i].to)^1;
        if(x!=y)merge(x,y,z);
        else if(z&1){for(int j=l;j<=r;j++)puts("NO");goto ed;}
    }
    if(l==r)puts("YES");
    else query(l,(l+r)>>1,pos<<1),query((l+r)/2+1,r,pos<<1|1);
    ed:for(int i=top;i>rec;i--){
        int fx=upd[i].fx,fy=upd[i].fy;
        dis[fx]=0,f[fx]=fx,size[fy]-=size[fx];
    }top=rec;
}
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1;i<=q;i++){
        scanf("%d%d",&edge[i].from,&edge[i].to);edge[i].tim=i;
        if((it=st.find(edge[i]))==st.end())st.insert(edge[i]);
        else insert(1,q,1,it->tim,i-1,edge[i]),st.erase(it);
    }
    for(it=st.begin();it!=st.end();it++)insert(1,q,1,it->tim,q,*it);
    query(1,q,1);
}

 

 

posted @ 2017-06-25 00:24  SiriusRen  阅读(150)  评论(0编辑  收藏  举报