贪心。
只能是竖着不递减的就尽量选上,当某一行出现字典序大于上一行的情况的时候,就不用再考虑这一行。
代码如下:
#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;
}
B - Tennis Game
二分。
枚举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;
}
C - Distributing Parts
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;
}