题目-最少01翻转次数 (51nod.com)(思维 前缀和 后缀和 枚举)
参考文献:(27条消息) 51nod 2517 最少01翻转次数_林子盛吧(✪ω✪)的博客-CSDN博客
思路:
序列不降的情况有三种:假设元素有6个
000000 000111 111111
也就是选定一个位置把此位置之前的1翻转为0,之后的1翻转为0以保证序列不降。因此我们枚举整个区间,对于每个ai,枚举前面有多少个1,后面有多少个0,因此我们利用前缀和和后缀和来统计每个位置ai的所有情况
这样对于每个位置情况预处理的序列都是合法的,所以我们只需要统计
每个位置的前缀和后缀和的最小值就行了
#include<bits/stdc++.h>
using namespace std;
const int N=2e4+10;
int head[N],tail[N];
char a[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
//预处理前缀和
for(int i=0;i<n;i++)
{
head[i+1]=head[i];
if(a[i]=='1') head[i+1]++;
}
//预处理后缀和
for(int i=n-1;i>=0;i--)
{
tail[i-1]=tail[i];
if(a[i]=='0') tail[i-1]++;
}
int res=0x3f3f3f3f;
for(int i=0;i<n;i++)
{
res=min(res,tail[i]+head[i]);
}
cout<<res<<endl;
}
Han Solo and Lazer Gun - CodeForces 514B - Virtual Judge (csgrandeur.cn)
题意:有一把枪,可以射击一条直线上的所有敌人(斜线也可以),现在给你枪的位置和n个敌人的坐标,求至少要射击多少次
错误:因为选择的语言不同g++14竟然错了,下次选最新版本hh
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n;
double x,y;
int main()
{
cin>>n>>x>>y;
int flag=0;set<double> st;
for(int i=0;i<n;i++)
{
double x1,y1;
cin>>x1>>y1;
if(x1==x) flag=1;
else
{
double k=(y-y1)/(x-x1);
st.insert(k);
}
}
cout<<st.size()+flag<<endl;
return 0;
}
程序设计:迷宫 - 计蒜客 43113 - Virtual Judge (csgrandeur.cn)
思路:bfs搜索,迷宫经典例题,优先考虑起点和是否进入传送门
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e3+10,M=1;
typedef pair<int,int> PII;
int n,m,endx,endy;
map<PII,PII> mp;
map<PII,bool> mp1;
char a[N][N];
int d[N][N];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
void bfs()
{
queue<PII> q;
memset(d,-1,sizeof(d));
d[1][1]=0;
q.push(make_pair(1,1));
while(q.size())
{
PII t=q.front();
q.pop();
if(a[t.first][t.second]=='*'||d[t.first][t.second]==-1) continue;
else if(mp1[make_pair(t.first,t.second)]==true)
{
d[mp[t].first][mp[t].second]=d[t.first][t.second];
//cout<<mp[t].first<<mp[t].second;
q.push(mp[t]);
}
else
{
for(int i=0;i<4;i++)
{
int x=t.first+dx[i],y=t.second+dy[i];
if(x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]=='.'&&d[x][y]==-1)
{
d[x][y]=d[t.first][t.second]+1;
q.push(make_pair(x,y));
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
int q;
cin>>q;
while(q--)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
//cout<<x1<<y1<<x2<<y2<<endl;
mp1[make_pair(x1,y1)]=true;
mp[make_pair(x1,y1)]=make_pair(x2,y2);
//cout<<mp[make_pair(x1,y1)].first<<" "<<mp[make_pair(x1,y1)].second<<"qaq"<<endl;;
}
cin>>endx>>endy;
bfs();
if(d[endx][endy]==-1)
{
cout<<"No solution"<<endl;
return 0;
}
cout<<d[endx][endy]<<endl;
return 0;
}
Fadi and LCM - CodeForces 1285C - Virtual Judge
思路:第一次写的时候tle了,原因是双重循环o(n*n),数据太大了,后来发现因为要求一个数对应数对的最大公约数是这个数且这个数对max尽可能要小,所以我们可以对这个数开平方在这个数的开平方数两边开始寻找
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
LL n;
LL gcd(LL a,LL b)
{
if(b==0)
{
return a;
}
return gcd(b,a%b);
}
LL lcm(LL a,LL b)
{
return (a*b)/gcd(a,b);
}
int main()
{
scanf("%lld",&n);
LL res=0;
for(LL i=1;i<=n/i;i++)
{
if(n%i==0&&lcm(i,n/i)==n)
{
res=i;
}
}
cout<<res<<" "<<n/res<<endl;
return 0;
}
Tallest Cow - POJ 3263 - Virtual Judge (csgrandeur.cn)
思路:差分,第一次写的时候错了,因为没有考虑一对牛被重复枚举的可能
#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
const int N=1e4+10,M=1;
int a[N],b[N];
int n,j,h,r;
typedef pair<int,int> PII;
map<PII,bool> mp;
void check(int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c;
}
int main()
{
cin>>n>>j>>h>>r;
for(int i=1;i<=n;i++) a[i]=h;
for(int i=1;i<=n;i++) b[i]=a[i]-a[i-1];
while(r--)
{
int x,y;
cin>>x>>y;
if(x>y) swap(x,y);
if(mp[make_pair(x,y)]) continue;
mp[make_pair(x,y)]=true;
check(x+1,y-1,-1);
}
for(int i=1;i<=n;i++) a[i]=b[i]+a[i-1];
for(int i=1;i<=n;i++) cout<<a[i]<<endl;
return 0;
}