Codeforces Round #345 (Div. 2)

D题:直接滑窗,枚举转折点,滑动结束点。水题啊水题。。。。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))
#define PII pair<int,int>

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n,a,b,T;
char s[maxn],t[maxn];
int look[maxn];

int solve(int dir)
{
    if(dir) reverse(s+2,s+n+1);
    REP(i,1,n) look[i]=s[i]=='w'?b+1:1;
    int ans=0;
    int cost=look[1],cnt=1;
    int x=1,y=n+1;
    /// find the last y
    while(y>1){
        y--;
        if(y==1){
            y++;break;
        }
        cost+=a+look[y];
        cnt++;
        if(cost>T){
            cnt--,cost-=a+look[y],y++;
            break;
        }
    }
    //cout<<"cnt="<<cnt<<" cost="<<cost<<" T="<<T<<endl;
    if(cost<=T) ans=max(ans,cnt);
    /// solve
    for(x=1;;){
        if(x+1==y) break;
        x++;
        cost+=2*a+look[x];
        cnt++;
        while(y<=n&&cost>T){
            cost-=look[y]+a;
            cnt--;
            y++;
        }
        if(cost<=T) ans=max(ans,cnt);
    }
    return ans;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n>>a>>b>>T){
        scanf("%s",s+1);
        int ans=0;
        REP(i,0,1) ans=max(ans,solve(i));
        cout<<ans<<endl;
    }
    return 0;
}

/**
4 2 3 10
wwhw

5 2 4 13
hhwhh

5 2 4 1000
hhwhh

3 1 100 10
whw

*/
View Code

E题:贪心+并查集。

将所有数拿出来从小到大排序,按顺序填进去,第一个肯定是填1,接着用如果当前要填的数为x,看x的所在行和所在列,要填的x必然大于等于所在行和所在列的最大值,如果大于的话很好处理,取最大值+1就可以了,关键在于等于的时候。这里用并查集维护,将在同一行或同一列相等的数用并查集连通起来,那么每次只要需要更新的时候只要更新并查集的祖先就可以了,反正无论找哪个都会找到它的祖先。而如果某个数在同行同列没有相等的,那么它的祖先就是它自己了。现在问题就解决了,每添加一个数,检查同行同列有没有相等的,如果有更新并查集的祖先或它,并将它和祖先连起来,如果没有直接更新就行了。分四种情况代码会比较清晰一些。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))
#define PII pair<int,int>

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;

int n,m;
int a[maxn];
PII b[maxn];int N;
int fa[maxn];
int val[maxn];
int rid[maxn],cid[maxn];/// 行最大值的位置,列最大值的位置

int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n>>m){
        REP(i,1,n) REP(j,1,m) scanf("%d",&a[(i-1)*m+j]);
        REP(i,1,n) fa[i]=i;
        N=n*m;
        REP(i,1,N) b[i]={a[i],i};
        sort(b+1,b+N+1);
        REP(i,1,N) fa[i]=i;
        MS0(val);
        MS0(rid);MS0(cid);
        int p1=b[1].second;
        int r1=(p1-1)/m+1,c1=p1%m;
        if(c1==0) c1=m;
        val[p1]=1;
        rid[r1]=cid[c1]=p1;
        REP(i,2,N){
            int p=b[i].second;
            int r=(p-1)/m+1,c=p%m;
            if(c==0) c=m;
            int x=find(rid[r]),y=find(cid[c]);
            if(a[p]>a[x]&&a[p]>a[y]){
                rid[r]=cid[c]=p;
                val[p]=max(val[x],val[y])+1;
            }
            else if(a[p]>a[x]&&a[p]==a[y]){
                rid[r]=p;
                val[p]=max(val[x]+1,val[y]);
                fa[y]=p;
            }
            else if(a[p]==a[x]&&a[p]>a[y]){
                cid[c]=p;
                val[p]=max(val[x],val[y]+1);
                fa[x]=p;
            }
            else{
                rid[r]=cid[c]=p;
                val[p]=max(val[x],val[y]);
                fa[x]=p;fa[y]=p;
            }
        }
        REP(i,1,n){
            REP(j,1,m){
                int x=find((i-1)*m+j);
                printf("%d ",val[x]);
            }
            puts("");
        }
    }
    return 0;
}

/**
2 2
1 2
3 4

4 3
20 10 30
50 40 30
50 60 70
90 80 70

1 1
1
2 2
2 2
2 2

4 3
7 8 8
5 1 4
3 2 8
4 5 4

*/
View Code

 

posted @ 2016-03-08 23:43  __560  阅读(278)  评论(0编辑  收藏  举报