//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:给出n个数对(a,b),使suma,sumb都为偶数最少需要交换几个数对。不能做到输出-1。
题解:求出suma,sumb判断是否需要交换。判断是否存在((a+b)&1)==1,存在才可以交换。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
int main() {
int n;
while(~scanf("%d",&n)) {
int x,y,sumx=0,sumy=0,flag=0;
for(int i=1;i<=n;++i) {
scanf("%d%d",&x,&y);
sumx+=x;
sumy+=y;
if((x+y)&1) flag=1;
}
if((sumx&1)&&(sumy&1)&&flag) {
puts("1");
} else if((sumx%2==0)&&(sumy%2==0)) {
puts("0");
} else {
puts("-1");
}
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:给出2n个数(10 ≤ ai ≤ 99),把他们均分成两部分A和B,A,B中重复出现的元素当成一个元素。求分配的方案,使|A|*|B|最大。
题解:把所有数分成:出现过两次以上和出现过两次以下的(包括两次)。(剩下的懒得写了,看代码吧)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=105;
struct Node {
int a,i;
}a[2*N],b[2*N],c[2*N];
bool cmp(Node a,Node b) {
if(a.a==b.a) return a.i<b.i;
return a.a<b.a;
}
int ans[2*N],ti[N];
map<int,int> mp1,mp2;
int main() {
int n;
while(~scanf("%d",&n)) {
int m=0,k=0;
memset(ti,0,sizeof(ti));
for(int i=1;i<=2*n;++i) {
scanf("%d",&a[i].a);
a[i].i=i;
++ti[a[i].a];
if(ti[a[i].a]<=2) b[++m]=a[i];
else c[++k]=a[i];
}
sort(b+1,b+1+m,cmp);
mp1.clear();
mp2.clear();
for(int i=1;i<=m;++i) {
int j=b[i].i;
if(i&1) {
ans[j]=1;
++mp1[b[i].a];
} else {
ans[j]=2;
++mp2[b[i].a];
}
}
for(int i=1;i<=k;++i) {
int j=c[i].i;
if((i+m)&1) {
ans[j]=1;
++mp1[c[i].a];
} else {
ans[j]=2;
++mp2[c[i].a];
}
}
printf("%d\n",mp1.size()*mp2.size());
for(int i=1;i<=2*n;++i) printf("%d%c",ans[i],(i==2*n)?'\n':' ');
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:给出n个数和一个二进制数m。,x属于1~m。求最大的f(x)
题解:一开始想的是,如果不取最高位,那么低位全为1肯定是最优的。现在如何判断取最高位的情况呢?
我们可以用i遍历最高位到最低位,i之前的位都不变,i之后的位都变成1(bit(i)==1)。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=100005;
int a[N],sum[N];
char s[N];
int main() {
int n;
while(~scanf("%d",&n)) {
for(int i=1;i<=n;++i) scanf("%d",a+i);
scanf("%s",s+1);
int p=-1;//最高位的1
for(int i=n;i>=1;--i) {
if(s[i]-'0') {
p=i;
break;
}
}
if(p==-1) {
puts("0");
continue;//没有1
}
//不变的情况
int ans=0;
for(int i=1;i<=n;++i) {
if(s[i]-'0') ans+=a[i];
sum[i]=sum[i-1]+a[i];
}
int res=0;
for(int i=p;i>=1;--i) {
//i之前的都不变,之后的都为1(当前位是1才可以)
if(s[i]-'0') {
ans=max(ans,res+sum[i-1]);
res+=a[i];
}
}
printf("%d\n",ans);
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=1000005;
char s[N];
int a[N],b[N];
int main() {
while(~scanf("%s",s+1)) {
int n=strlen(s+1);
int m=0,cnt=0;
for(int i=1;i<=n;++i) {
if(s[i]=='F') {
a[i]=i-(++m);//要往前移动多少
if(a[i]) b[i]=cnt++;//会被堵住多久(跳过开头的FFF)
} else {
if(cnt) --cnt;
}
}
int ans=0;
for(int i=1;i<=n;++i) {
if(s[i]=='M') continue;
if(a[i]) ans=max(ans,a[i]+b[i]);
//printf("%d %d %d\n",i,a[i],b[i]);
}
printf("%d\n",ans);
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
题意:有一个图,结点编号0~n-1。用一个长度n,只由01组成的字符串s[0~n-1]表示图的所有边。 s[i]==0表示有向边<i,i+1>, s[i]==1表示有向边<i+1,i>。如果u能到达v或者v能到达u,那么称u与v可达。找出一个最大的集合,集合中的点互不可达。输出集合大小。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=1000005;
char s[N];
int a[N];
int main() {
while(~scanf("%s",s+1)) {
int n=strlen(s+1);
int m=0,cnt=0;
s[0]=s[1];
s[n+1]=1-(s[n]-'0')+'0';
for(int i=1;i<=n+1;++i) {
if(s[i]==s[i-1]) {
++cnt;
} else {
a[++m]=cnt;
cnt=1;
}
}
if(m&1) {
a[1]+=a[m];
--m;
}
int flag=0;
for(int i=1;i<=m;++i) {
if(a[i]>=2) flag=1;
}
//去掉这个也能AC,但是有反例
//100110
int p=1;
if(flag) {
while(a[p]==1) {
a[++m]=a[p++];
}
}
int ans=0; cnt=0;
for(int i=p;i<=m;++i) {
if(a[i]>=2) {
ans+=cnt/2+1;
cnt=0;
} else {
++cnt;
}
}
ans+=cnt/2;
printf("%d\n",ans);
}
return 0;
}