A - Amusement Anticipation
题意:找到间隔相同的最长的子串,这个串以最后一个元素为开头
#include <iostream>
#include <stdio.h>
#include <bits/stdc++.h>
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;
}
B - Pond Cascade
题意:给出n个水池,大小不同,给出流速,当一个水池装满水后会溢出,求最后一个水池装满的时间和全部装满的时间。
分析:这个题有三种做法,二分 / 优先队列 / 贪心
二分:规定一下二分的次数
#include<bits/stdc++.h>
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; i<n; ++i)flow[i]=F*t;
for(int i=0; i<n-1; ++i)
{
if(flow[i]>cap[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<n; ++i)
scanf("%lf",&cap[i]);
//for(int i=0;i<n;++i)printf("%f\n",cap[i]);
double ans1,ans2;
double l=0,r=1e9+10;
for(int i=0;i<100;++i)
{
double mid=(l+r)/2.0;
judge(mid,0)?r=mid:l=mid;
}
ans1=l;
l=0,r=1e9+10;
for(int i=0;i<100;++i)
{
double mid=(l+r)/2.0;
judge(mid,1)?r=mid:l=mid;
}
ans2=l;
printf("%.8f %.8f\n",ans1,ans2);
}
return 0;
}
优先队列:每次求最先装满的那个,用双向链表保存前后水池关系
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
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_queue<Node>q;
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<<t[i]<<endl;
}
hail[n+1] = n;
tial[0] = 1;
while(!q.empty()){
Node now = q.top();q.pop();
if(vis[now.id]) continue;
vis[now.id] = true;
last_time = now.time;
//cout<<last_time<<endl;
if(now.id == n) tagert_time = last_time;
int fr = hail[now.id];
int nx = tial[now.id];
hail[nx] = fr;
tial[fr] = nx;
if(nx!=n+1){
cap[nx] -= (last_time - lt[nx])*flow[nx];
flow[nx] += flow[now.id];
lt[nx] = last_time;
t[nx] = cap[nx]/flow[nx];
q.push({nx,t[nx]+lt[nx]});
}
}
printf("%.8f %.8f\n",tagert_time,last_time);
}
}
贪心:对于输出第n个满的时间,第n个可能是单独的不靠前面的流向它或者靠前面的流向它,时间就是后面m个的总容量除以后面m个的总速度的最小值就是第n个的时间。而最后流满的时间是第一个流满时间,第一个和第二个加起来流满时间,第1,2,3个加起来流满时间,第……的最大值
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
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);
}
}
C - Chessboard Dancing
#include<bits/stdc++.h>
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<<endl;
else cout<<4<<endl;
}
else if(c=='N'){
if(n==1||n==2) cout<<1<<endl;
else cout<<2<<endl;
}
else cout<<n<<endl;
}
}
D - Equinox Roller Coaster
E - Forest Picture
题意:模拟,队友写的
#include<bits/stdc++.h>
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<<g[i][j];
}
cout<<endl;
}
}
bool ok(int a,int b)
{
if(a>=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<<endl;
}
}
F - Shooting Gallery
题意:给出一串数字,相同数字可连起来形成一个区间,求最大的区间覆盖数
分析:DP
记忆化搜索
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <deque>
#define ll long long
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
using namespace std;
typedef pair<int,int> pii;
const int maxn = 5000 + 7, inf = 0x3f3f3f3f;
int dp[maxn][maxn];
int n;
int a[maxn];
int dfs(int L,int R){
if(L>=R) return 0;
if(dp[L][R]!=-1) return dp[L][R];
if(a[L]==a[R]) return dp[L][R] = 1 + dfs(L+1, R-1);
else return dp[L][R] = max(dfs(L+1, R), dfs(L,R-1));
}
int main(){
//FRER();
while(~scanf("%d",&n)){
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
dp[i][j] = -1;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
printf("%d\n",dfs(1, n));
}
}
区间DP
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <deque>
#define ll long long
#define lowbit(x) (x&(-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("in.txt","r",stdin);
#define FREW() freopen("out.txt","w",stdout);
using namespace std;
typedef pair<int,int> pii;
const int maxn = 5000 + 7, inf = 0x3f3f3f3f;
int dp[maxn][maxn];
int n;
int a[maxn];
int main(){
//FRER();
while(~scanf("%d",&n)){
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
dp[i][j] = 0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
if(a[i]==a[i+len-1]){
dp[i][i+len-1] = max(dp[i][i+len-1],dp[i+1][i+len-2]+1);
}
else dp[i][i+len-1] = max(dp[i+1][i+len-1],dp[i][i+len-2]);
//printf("dp[%d][%d] = %d\n",i,i+len-1,dp[i][i+len-1]);
}
}
cout<<dp[1][n]<<endl;
}
}
G - Ice cream samples
尺取法
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 2e6 + 7, inf = 0x3f3f3f3f;
int n,k,m;
int cnt;
int ans;
struct Node{
int len;
vector<int>v;
}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<k&&r<=2*n){
for(int i=0;i<s[r].len;i++){
m = s[r].v[i];
if(!vis[m]) cnt++;
vis[m]++;
}
r++;
}
if(r>=2*n+1) break;
if(cnt==k){
ans = min(ans,sum[r-1]-sum[l-1]);
for(int i=0;i<s[l].len;i++){
m = s[l].v[i];
vis[m]--;
if(!vis[m]) cnt--;
}
l++;
}
}
printf("%d\n",ans==inf?-1:ans);
for(int i=1;i<=2*n;i++){
s[i].v.clear();
}
}
}
H - Dark Ride with Monsters
题意:给出一个序列,问交换几次可以使得序列有序,暴力
#include<bits/stdc++.h>
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;i<n;i++)
{
scanf("%d",&s[i]);
t[i]=s[i];
}
sort(t,t+n);
for(int i=0;i<n;i++)
m[t[i]]=i;
queue<int>q;
int ans=0;
for(int i=0;i<n;i++)
{
int tep=m[s[i]];
while(tep!=i)
{
swap(s[i],s[tep]);
ans++;
tep=m[s[i]];
}
}
printf("%d\n",ans);
}
}
I - Go Northwest!
题意:给出若干个点,求所有两个点的组合中,在一条对角线的组合的比率
#include<bits/stdc++.h>
using namespace std;
typedef map<long long,long long> 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);
}
}
J - Punching Power
题意:给你二维平面的一些点,让你从这n个点中选择一些点,让这些点任意两点的距离要大于1.3
分析:二分图匹配,把相距为1的点建边,跑出最大匹配ans,n-ans即为答案
#include<bits/stdc++.h>
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<n; ++i)
scanf("%d%d",&x[i],&y[i]);
for(int i=0; i<n; ++i)
for(int j=i+1; j<n; ++j)
{
if((abs(x[i]-x[j])==1&&y[i]==y[j])||(abs(y[i]-y[j])==1&&x[i]==x[j]))
{
AddEdge(i,j);
AddEdge(j,i);
}
}
//printf("nedge=%d\n",nEdge);
int ans=0;
memset(op,-1,sizeof op);
for(int i=0;i<n;++i)
{
memset(vis,0,sizeof vis);
if(!~op[i]&&match(i))++ans;
}
printf("%d\n",n-ans);
}
return 0;
}