贪心。
只能是竖着不递减的就尽量选上,当某一行出现字典序大于上一行的情况的时候,就不用再考虑这一行。
代码如下:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <stdio.h> using namespace std; char s[1002][1002]; int a[1002]; int main() { int n, m, i, j, ans, flag; while(scanf("%d%d",&n,&m)!=EOF){ memset(a,0,sizeof(a)); for(i=0;i<n;i++){ scanf("%s",s[i]); } ans=0; flag=0; for(i=0;i<m;i++){ for(j=1;j<n;j++){ if(!flag&&s[j][i]<s[j-1][i]){ flag=1; ans++; break; } else if(flag&&!a[j]&&s[j][i]<s[j-1][i]){ flag=1; ans++; break; } } if(j>=n) { flag=1; for(j=1;j<n;j++){ if(s[j][i]>s[j-1][i]){ a[j]=1; } } } } printf("%d\n",ans); } return 0; }
二分。
枚举t,然后不断二分找下一个节点并判断是否可行。时间复杂度为n*log(n)*log(n)。
代码如下:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <stdio.h> using namespace std; int s[110000], dp1[110000], dp2[110000], c1[110000], c2[110000]; int bin_search(int x, int y, int n) { int low=1, high=n, mid, ans=n+1; while(low<=high) { mid=low+high>>1; if(dp1[mid]>=x||dp2[mid]>=y) { high=mid-1; ans=mid; } else low=mid+1; } return ans; } struct node { int s, t; } fei[100000]; int cmp(node f1, node f2) { if(f1.s==f2.s) return f1.t<f2.t; return f1.s<f2.s; } int main() { int n, a, b, i, c, ans1, ans2, sum1, sum2, k, flag, cnt, tmp; while(scanf("%d",&n)!=EOF) { cnt=0; dp1[0]=dp2[0]=0; for(i=1; i<=n; i++) { scanf("%d",&s[i]); if(s[i]==1) { dp1[i]=dp1[i-1]+1; dp2[i]=dp2[i-1]; } else { dp1[i]=dp1[i-1]; dp2[i]=dp2[i-1]+1; } } for(i=n; i>=1; i--) { sum1=sum2=0; flag=ans1=ans2=0; k=0; tmp=0; while(k<n) { k=bin_search(sum1+i,sum2+i,n); if(k==n+1) continue ; if(dp1[k]==sum1+i) { ans1++; tmp=1; } else { ans2++; tmp=2; } sum1=dp1[k]; sum2=dp2[k]; } if(k==n&&ans1!=ans2) { if((ans1>ans2&&tmp==2)||(ans1<ans2&&tmp==1)) continue ; fei[cnt].t=i; fei[cnt++].s=max(ans1,ans2); } } printf("%d\n",cnt); sort(fei,fei+cnt,cmp); for(i=0; i<cnt; i++) { printf("%d %d\n",fei[i].s,fei[i].t); } } return 0; }
STL+贪心。
不会用set啊。。用上set这题就变得这么简单了。。醉了。。
先降维,将二维变成一维,那就先按右端点值或者左端点值排序。那就只剩下找另一端点了,用二分就可以了。
代码如下:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using namespace std; #define LL __int64 int d[110000]; struct node { int l, r, k, id; } a[110000], b[110000]; int cmp(node f1, node f2) { if(f1.r==f2.r) return f1.l<f2.l; return f1.r<f2.r; } struct point { int x, id; point() {} point(int x, int id):x(x),id(id) {} bool operator < (const point& a) const { if(x==a.x) return id<a.id; return x<a.x; } }; int main() { int n, i, j, k, m, cnt; scanf("%d",&n); for(i=0; i<n; i++) { scanf("%d%d",&a[i].l,&a[i].r); a[i].id=i; } scanf("%d",&m); for(i=0; i<m; i++) { scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].k); b[i].id=i; } set<point>q; q.clear(); set<point>::iterator it; sort(a,a+n,cmp); sort(b,b+m,cmp); j=0; cnt=0; for(i=0; i<m; i++) { while(j<n&&a[j].r<=b[i].r) { q.insert(point(a[j].l,a[j].id)); j++; } for(k=0; k<b[i].k; k++) { it=q.lower_bound(point(b[i].l,-1)); if(it==q.end()) { break; } point tmp=*it; d[tmp.id]=b[i].id; q.erase(tmp); cnt++; } } if(cnt<n) puts("NO"); else { puts("YES"); for(i=0; i<n; i++) { printf("%d ",d[i]+1); } } return 0; }
时间: 2024-10-08 09:44:54