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 */
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 */
没有AC不了的题,只有不努力的ACMER!