题意:找到间隔相同的最长的子串,这个串以最后一个元素为开头
#include
#include
#include
using namespace std;
int main()
{
long long a[1000+10], ans;
int n, i;
while(scanf("%d",&n)!=EOF)
{
int f = 1;
ans = 0;
for(i = 1; i<=n; i++)
scanf("%lld",&a[i]);
ans = a[n]-a[n-1];
for(i = n; i>=1; i--)
{
if(a[i]-a[i-1]!=ans)
{
printf("%d\n",i);
f = 0;
break;
}
}
if(f==1)
printf("1\n");
}
return 0;
}
题意:给出n个水池,大小不同,给出流速,当一个水池装满水后会溢出,求最后一个水池装满的时间和全部装满的时间。
分析:这个题有三种做法,二分 / 优先队列 / 贪心
二分:规定一下二分的次数
#include
using namespace std;
const int N=1e5+10;
const double eps=1e-7;
int n;
double F,cap[N],flow[N];
bool judge(double t,int flag)
{
for(int i=0; icap[i])flow[i+1]+=flow[i]-cap[i];
else if(flag)return false;
}
return flow[n-1]>cap[n-1];
}
int main()
{
//freopen("i.txt","r",stdin);
while(scanf("%d%lf",&n,&F)==2)
{
for(int i=0; i
优先队列:每次求最先装满的那个,用双向链表保存前后水池关系
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1e5 + 7;
int n;
double f;
int hail[maxn],tial[maxn];//链表头尾
bool vis[maxn];
double cap[maxn];//剩余容量
double t[maxn];//总时间
double lt[maxn];//更新容量前的时间
double flow[maxn];//流速
struct Node{
int id;
double time;
bool operator < (const Node& rhs) const {
return time > rhs.time;
}
};
priority_queueq;
int main(){
while(~scanf("%d%lf",&n,&f)){
double last_time = 0,tagert_time = 0;
while(!q.empty()) q.pop();
memset(vis, 0, sizeof(vis));
memset(t, 0, sizeof(t));
memset(lt, 0, sizeof(lt));
for(int i=1;i<=n;i++){
hail[i] = i-1;
tial[i] = i+1;
flow[i] = f;
scanf("%lf",&cap[i]);
t[i] = cap[i]/f;
q.push({i,t[i]});
//cout<
贪心:对于输出第n个满的时间,第n个可能是单独的不靠前面的流向它或者靠前面的流向它,时间就是后面m个的总容量除以后面m个的总速度的最小值就是第n个的时间。而最后流满的时间是第一个流满时间,第一个和第二个加起来流满时间,第1,2,3个加起来流满时间,第……的最大值
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 1e5 + 7;
int n;
double f;
double cap[maxn];
int main(){
while(~scanf("%d%lf",&n,&f)){
for(int i=1;i<=n;i++)
scanf("%lf",&cap[i]);
double sum = cap[n] , flow = f;
double res1 = cap[n]/f;
for(int i=n-1;i>=1;i--){
sum += cap[i];
flow += f;
res1 = min(res1,sum/flow);
}
double res2 = cap[1]/f;
sum = cap[1];
flow = f;
for(int i=2;i<=n;i++){
sum += cap[i];
flow += f;
res2 = max(res2,sum/flow);
}
printf("%.8f %.8f\n",res1,res2);
}
}
#include
using namespace std;
int main()
{
//freopen("i.txt","r",stdin);
int n;
char c;
while(~scanf("%d %c",&n,&c))
{
if(c=='K'){
if(n==1) cout<<1<
题意:模拟,队友写的
#include
using namespace std;
char g[200][200];
int m,n;
void init()
{
for(int i=0; i<=m+1; i++)
{
for(int j=0; j<=m+1; j++)
{
if(!i||!j||i==m+1||j==m+1)
g[i][j]='*';
else
g[i][j]='.';
}
}
}
void test()
{
for(int i=0; i<=m+1; i++)
{
for(int j=0; j<=m+1; j++)
{
cout<=1&&a<=m&&b>=1&&b<=m)
return true;
return false;
}
void getstump(int x,int y)
{
if(ok(x,y))
g[x][y]='o';
if(ok(x,y-1))
g[x][y-1]='_';
if(ok(x,y+1))
g[x][y+1]='_';
}
void gettree(int h,int x,int y)
{
if(ok(x,y))
g[x][y]='|';
if(ok(x,y-1))
g[x][y-1]='_';
if(ok(x,y+1))
g[x][y+1]='_';
for(int i=1; i<=h; i++)
{
int a=x-i;
if(ok(x-i,y))
g[x-i][y]='|';
if(ok(x-i,y-1))
g[x-i][y-1]='/';
if(ok(x-i,y+1))
g[x-i][y+1]='\\';
}
if(ok(x-h-1,y))
g[x-h-1][y]='^';
}
int main()
{
//freopen("i.txt","r",stdin);
while(~scanf("%d %d",&m,&n))
{
init();
while(n--)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
b=b+1;
c=m-c;
if(!a)
getstump(c,b);
else
gettree(a,c,b);
}
test();
cout<
题意:给出一串数字,相同数字可连起来形成一个区间,求最大的区间覆盖数
分析:DP
记忆化搜索
#include
区间DP
#include
尺取法
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 2e6 + 7, inf = 0x3f3f3f3f;
int n,k,m;
int cnt;
int ans;
struct Node{
int len;
vectorv;
}s[maxn];
int vis[maxn],sum[maxn];
int main(){
while(~scanf("%d%d",&n,&k)){
cnt = 0;
ans = inf;
memset(vis, 0, sizeof(vis));
for(int i=1;i<=n;i++){
scanf("%d",&s[i].len);
for(int j=1;j<=s[i].len;j++){
scanf("%d",&m);
s[i].v.push_back(m);
}
sum[i] = s[i].len;
sum[i+n] = sum[i];
s[i+n] = s[i];
}
for(int i=1;i<=2*n;i++)
sum[i]+=sum[i-1];
int l = 1 , r = 1;
while(l<=r){
if(r-l+1>n) break;
while(cnt=2*n+1) break;
if(cnt==k){
ans = min(ans,sum[r-1]-sum[l-1]);
for(int i=0;i
题意:给出一个序列,问交换几次可以使得序列有序,暴力
#include
using namespace std;
const int maxn=2*1e5+10;
int s[maxn],t[maxn],m[10*maxn];
int main()
{
//freopen("i.txt","r",stdin);
int n;
while(~scanf("%d",&n))
{
for(int i=0;iq;
int ans=0;
for(int i=0;i
题意:给出若干个点,求所有两个点的组合中,在一条对角线的组合的比率
#include
using namespace std;
typedef map ma;
ma m;
int main()
{
//freopen("i.txt","r",stdin);
long long n;
while(~scanf("%lld",&n))
{
m.clear();
long long N=n*n;
while(n--)
{
long long x,y;
scanf("%lld %lld",&x,&y);
m[x+y]++;
m[x-y]++;
}
long long M=0;
for(ma::iterator it=m.begin();it!=m.end();it++)
{
M+=(it->second)*(it->second-1);
}
printf("%.8f\n",(double)M/N);
}
}
题意:给你二维平面的一些点,让你从这n个点中选择一些点,让这些点任意两点的距离要大于1.3
分析:二分图匹配,把相距为1的点建边,跑出最大匹配ans,n-ans即为答案
#include
using namespace std;
const int N=2000+10;
const int M=N*20;
int n;
int head[N],to[M],nxt[M],nEdge;
int x[N],y[N],op[N],vis[N];
void AddEdge(int u,int v)
{
nxt[nEdge]=head[u],to[nEdge]=v,head[u]=nEdge++;
}
bool match(int u)
{
//printf("u=%d\n",u);
for(int e=head[u];~e;e=nxt[e])
{
int v=to[e];
if(vis[v])continue;
vis[v]=1;
if(!~op[v]||match(op[v]))
{
op[v]=u,op[u]=v;
return true;
}
}
return false;
}
int main()
{
//freopen("i.txt","r",stdin);
while(scanf("%d",&n)==1)
{
memset(head,-1,sizeof head);
nEdge=0;
for(int i=0; i