A.3132

给一个有向图,问能否从任意点出发都能进入一个环中。

深搜。

#include<bits/stdc++.h>
using namespace std; const int N=;
vector<int>G[N];
bool vis[N];
int f;
void dfs(int u)
{
if(f)return;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(!vis[v])
{
vis[v]=;
dfs(v);
}
else
{
f=;
return;
}
}
}
int main()
{
int n,m;
char s1[],s2[];
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=;i<=n;i++)G[i].clear();
for(int i=;i<m;i++)
{
int u,v;
scanf("%s%s",s1,s2);
G[s1[]-'A'+].push_back(s2[]-'A'+);
}
for(int i=;i<=n;i++)
{
f=;
memset(vis,,sizeof vis);
dfs(i);
if(!f)break;
}
printf("%s\n",f?"YES":"NO");
}
return ;
}

A.cpp

B.4971

给一颗树,n个起点,问到1的路径权值和,一个点的权值只算一次。

深搜。

#include<bits/stdc++.h>
using namespace std; const int N=;
vector<int>G[N];
bool vis[N];
int father[N],be[N],val[N];
void dfs(int u,int fa)
{
father[u]=fa;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa)continue;
dfs(v,u);
}
}
int main()
{
int n,m,ca=;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(vis,,sizeof vis);
for(int i=;i<=n;i++)G[i].clear();
for(int i=;i<=m;i++)
scanf("%d",&be[i]);
for(int i=;i<=n;i++)
scanf("%d",&val[i]);
for(int i=;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(,);
int sum=;
for(int i=;i<=m;i++)
{
int f=be[i];
if(!vis[f])vis[f]=,sum+=val[f];
while(f)
{
f=father[f];
if(!vis[f])vis[f]=,sum+=val[f];
}
}
printf("Case #%d: %d\n",ca++,sum);
}
return ;
}

B.cpp

C.4976

给一个二进制串,其中有一堆未知数,问有几种填法使得十进制数中含6。

深搜。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int p[]; string s;
int l;
int num=;
void dfs(int pos,ll ans)
{
if(pos==l)
{
while(ans)
{
if(ans%==)
{
num++;
break;
}
ans=ans/;
}
return;
}
if(s[pos]=='') dfs(pos+,ans*);
else if(s[pos]=='') dfs(pos+,ans*+);
else
{
dfs(pos+,ans*);
dfs(pos+,ans*+);
}
}
int main()
{
while(cin>>s)
{
num=;
l=s.size();
dfs(,);
cout<<num<<endl;
}
return ;
}

C.cpp

D.4546

M段区间每段区间只能有一张假票,问最多能有几张假票,若不合法输出-1。

不会(待补)

#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
#define MAXN 200010 int DP[MAXN];
int RMN[MAXN];
int RMX[MAXN]; template <class T>
struct max_queue
{
max_queue(size_t sz) : X(sz), Y(sz), a(), b(), va(), vb()
{}
void push(const T& v)
{
while(va < vb && X[vb - ] <= v)
vb--;
X[vb] = v;
Y[vb++] = b++;
} void pop()
{
va += a++ == Y[va];
} T max()
{
return X[va];
} vector<T> X;
vector<size_t> Y;
size_t a, b, va, vb;
}; int main() {
// freopen("d:\\data1.in","r",stdin);
// freopen("d:\\data1.out","w",stdout);
int N, M; scanf("%d%d", &N, &M);
fill(RMN, RMN + N + , N + );
for(int i = ; i < M; i++)
{
int lft, rht; scanf("%d%d", &lft, &rht);
RMN[lft] = min(RMN[lft], rht + );
RMX[lft] = max(RMX[lft], rht + );
}
RMN[N + ] = N + ;
for(int i = N - ; i >= ; i--)
{
RMN[i] = min(RMN[i], RMN[i + ]);
}
for(int i = ; i <= N; i++)
{
RMX[i] = max(RMX[i], RMX[i - ]);
}
DP[N + ] = ; int j_lo = N;
int j_hi = N;
max_queue<int> mq(N);
for(int i = N; i >= ; i--)
{
int r_least = max(i + , RMX[i]);
int r_most = RMN[i + ];
for(; r_least <= j_lo; j_lo--)
{
mq.push(DP[j_lo]);
}
for(; j_lo < j_hi && r_most <= j_hi; j_hi--)
{
mq.pop();
}
DP[i] = r_least < r_most ? mq.max() : -;
if(i && DP[i] != -)
{
DP[i]++;
}
} printf("%d\n", DP[]);
return ;
}

D.cpp by crq

E.4587

有两颗苹果树,贝西初始站在1下,每分钟掉下1个苹果,贝西最多移动W次,问T分钟贝西最多能接到多少苹果。

dp[t][w][3]表示在t分钟移动w次现在站在苹果树几下。

#include<bits/stdc++.h>
using namespace std;
int dp[][][];
int main()
{
for(int i=;i<;i++)
for(int j=;j<;j++)
dp[i][j][]=dp[i][j][]=-;
int T,W;
scanf("%d%d",&T,&W);
for(int i=;i<T;i++) dp[i][W][]=;
for(int i=,x;i<T;i++)
{
scanf("%d",&x);
if(!i)
{
if(x==) dp[i][W][]=;
else if(x==) dp[i][W-][]=;
}
else
{
for(int j=W;j>=;j--)
{
if(x==)
{
dp[i][j][]=max(dp[i][j][],dp[i-][j][]+);
if(j!=W) dp[i][j][]=max(dp[i][j][],dp[i-][j+][]+);
dp[i][j][]=max(dp[i][j][],dp[i-][j][]);
if(j!=W) dp[i][j][]=max(dp[i][j][],dp[i-][j+][]);
}
else if(x==)
{
dp[i][j][]=max(dp[i][j][],dp[i-][j][]+);
if(j!=W) dp[i][j][]=max(dp[i][j][],dp[i-][j+][]+);
dp[i][j][]=max(dp[i][j][],dp[i-][j][]);
if(j!=W) dp[i][j][]=max(dp[i][j][],dp[i-][j+][]);
}
}
}
}
int ans=;
for(int i=;i<=W;i++)
ans=max(ans,max(dp[T-][i][],dp[T-][i][]));
printf("%d\n",ans);
return ;
}

E.cpp

F.4596

n个盒子按1-n编号,m次操作,1XY把x放在y左边,2XY把x放在y右边,3XYxy互换位置,4翻转,问操作完所有奇数位置的盒子编号之和。

双向链表,L[i]=i-1,R[i]=i+1,然后4操作后1和2操作是反过来的,3操作的交换可能存在相邻两个,这时候要判断左右。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
int L[N],R[N];
int main()
{
int n,m,o=;
while(~scanf("%d%d",&n,&m))
{
for(int i=;i<=n+;i++) L[i]=i-,R[i]=i+;
int r=;
while(m--)
{
int op,x,y;
scanf("%d",&op);
if(op==)r=!r;
else
{
scanf("%d%d",&x,&y);
if(op==&&R[y]==x)swap(x,y);
if(op!=&&r)op=-op;
if(op==)
{
if(x==L[y])continue;
R[L[x]]=R[x];
L[R[x]]=L[x];
L[x]=L[y];
R[x]=y;
R[L[y]]=x;
L[y]=x;
}
else if(op==)
{
if(x==R[y])continue;
R[L[x]]=R[x];
L[R[x]]=L[x];
L[x]=y;
R[x]=R[y];
L[R[y]]=x;
R[y]=x;
}
else if(op==)
{
if(R[x]==y||L[x]==y||R[y]==x||L[y]==x)
{
R[L[x]]=y;
L[R[y]]=x;
L[y]=L[x];
R[x]=R[y];
R[y]=x;
L[x]=y;
}
else
{
R[L[x]]=L[R[x]]=y;
R[L[y]]=L[R[y]]=x;
swap(L[x],L[y]);
swap(R[x],R[y]);
}
}
}
}
long long sum=;
for(int i=R[];i<=n;i=R[R[i]]) sum+=i;
if(r&&(n&)==) sum=1LL*n*(n+)/-sum;
printf("Case %d: %I64d\n",++o,sum);
}
return ;
}

F.cpp

G.5066

n个点m条有向边,问从1出发最多经过几个点再回到1。

targin求含有1的强连通集合。

#include<bits/stdc++.h>
using namespace std; const int N=1e5+;
int low[N],dfn[N],Stack[N],tot,cnt;
bool instack[N];
vector<int>G[N];
void tarjan(int u)
{
int v;
dfn[u]=low[u]=++tot;
Stack[++cnt]=u;
instack[u]=true;
for(int i=;i<G[u].size();i++)
{
v=G[u][i];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int sz=;
while(v=Stack[cnt--])
{
instack[v]=false;
sz++;
if(u==v)break;
}
if(u==)printf("%d\n",sz);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
tarjan();
return ;
}

G.cpp

H.5129(题面已经修正)

n个人的无向图,LJ为1和LJ已经认识的人,对于S,输出LJ可以认识的新朋友,对于Q x,输出1和x是否连通。

并查集。

坑点:

1.LJ可以认识自己。

2.n和m是相反的。

#include<bits/stdc++.h>
using namespace std;
int f[];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
int main()
{
ios::sync_with_stdio(false),cin.tie(),cout.tie();
int n,m,t,g,val,k,v;
cin>>t;
while(t--)
{
cin>>m>>n;
for(int i=;i<=n;i++)f[i]=i;
for(int i=;i<=n;i++)
{
cin>>k;
if(i==)g=k;
for(int j=;j<k;j++)
{
cin>>v;
if(i==&&i==v)g--;
int fu=find(i),fv=find(v);
if(fu!=fv)f[fu]=fv;
}
}
for(int i=;i<=n;i++)f[i]=find(i);
string s;
int ans=;
for(int i=;i<=n;i++)
if(f[]==f[i])
ans++;
while(m--)
{
cin>>s;
if(s[]=='S')
cout<<ans-g<<'\n';
else
{
cin>>val;
if(f[]==f[val])cout<<"Yes!\n";
else cout<<"No!\n";
}
}
}
return ;
}

H.cpp

I.5166

n个点构造一个哈夫曼树。

贪心每次取两个最小的。

#include<bits/stdc++.h>
using namespace std; int main()
{
priority_queue< int,vector<int>,greater<int> >q;
int n;
cin>>n;
for(int i=;i<=n;i++)
{
int a;
cin>>a;
q.push(a);
}
int sum=;
while(q.size()>)
{
int a=q.top();q.pop();
int b=q.top();q.pop();
sum+=a+b;
q.push(a+b);
}
cout<<sum;
return ;
}

I.cpp

J.4992

n次移动,(0,0)朝北出发,每次走ai步,走完后右转,如果路径冲突,输出移动了几次,否则输出OK。

首先几何知识判断两条线段是否相交或重叠。

通过观察发现当前这条线段最多和前面8条线段存在冲突。

#include <cstdio>
#include <algorithm>
using namespace std; const int MAX = , dx[] = { , , , - }, dy[] = { , , -, };
int N, a[MAX]; struct Point
{
int x, y;
Point(int _x = , int _y = ) :
x(_x), y(_y) {}
} points[MAX]; // true, if intervals [a,b] and [c,d] have non-empty intersection
bool overlap(int a, int b, int c, int d)
{
if (a > b) swap(a, b);
if (c > d) swap(c, d);
return !(b < c || d < a);
} // true if line segments [a1,a2] and [b1,b2] have non-empty intersection
bool intersect(Point a1, Point a2, Point b1, Point b2)
{
bool is_vertical_a = (a1.x == a2.x), is_vertical_b = (b1.x == b2.x);
if (is_vertical_a && is_vertical_b)
return a1.x == b1.x && overlap(a1.y, a2.y, b1.y, b2.y);
if (!is_vertical_a && !is_vertical_b)
return a1.y == b1.y && overlap(a1.x, a2.x, b1.x, b2.x);
// make a horizontal and b vertical
if (is_vertical_a)
{
swap(a1, b1);
swap(a2, b2);
}
return !(
max(a1.x, a2.x) < b1.x ||
min(a1.x, a2.x) > b1.x ||
max(b1.y, b2.y) < a1.y ||
min(b1.y, b2.y) > a1.y);
} int solve()
{
int x = , y = ;
for (int i = ; i < N; ++i)
{
x += dx[i & ] * a[i];
y += dy[i & ] * a[i];
points[i + ].x = x;
points[i + ].y = y;
for (int j = max(, i - ); j < i - ; ++j)
if (intersect(points[j], points[j + ], points[i], points[i + ]))
return i;
}
return -;
} int main()
{
while (scanf("%d", &N) == )
{
for (int i = ; i < N; ++i)
scanf("%d", a + i);
int result = solve();
if (result == -)
printf("OK\n");
else
printf("%d\n", result);
} return ;
}

J.cpp

K.4541

n个数,求插入个数最少的整数,使其成为一个回文数列。

dp,答案是n-最长回文子序列的长度。

设字符串为s,f(i,j)表示s[i..j]的最长回文子序列。

状态转移方程如下:

当i>j时,f(i,j)=0。

当i=j时,f(i,j)=1。

当i<j并且s[i]=s[j]时,f(i,j)=f(i+1,j-1)+2。

当i<j并且s[i]≠s[j]时,f(i,j)=max( f(i,j-1), f(i+1,j) )。

由于f(i,j)依赖i+1,所以循环计算的时候,第一维必须倒过来计算,从s.length()-1到0。

最后,s的最长回文子序列长度为f(0, s.length()-1)。

可以发现计算第i行时只用到了第i+1行,所以可以滚动数组减少内存使用。

#include<bits/stdc++.h>
using namespace std;
const int N=;
int a[N],n,dp[][N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(dp,,sizeof dp);
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
int cnt=;
for(int i=n;i>=;i--)
{
cnt^=;
memset(dp[cnt],,sizeof dp[cnt]);
dp[cnt][i]=;
for(int j=i+;j<=n;j++)
{
if(a[i]==a[j]) dp[cnt][j]=dp[cnt^][j-]+;
else dp[cnt][j]=max(dp[cnt][j-],dp[cnt^][j]);
}
}
printf("%d\n",n-dp[cnt][n]);
}
return ;
}

K.cpp

L.4561

n个人,1号为Sheldon,已知其余n-1个人投给了f[i]要买通需要花费c[i],1号需要投给1个人。最后1想要花最少的钱使得自己的票数>其他所有人的票数,求最少的钱。

贪心+讨论

这里每个人票数为p[i]。

1投给目前票数最少的人(好好思考思考),然后考虑1需要x票能赢,那么其余人i只要p[i]>=x就需要买通p[i]-x+1个人,肯定买最便宜的,最后如果1还差k票,那么把所有没买通的人按c[i]排序再取k个最小。

#include<bits/stdc++.h>
using namespace std;
vector<int>vec[];
int f[],c[],t,a;
int main()
{
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=;i<=n;i++)vec[i].clear();
for(int i=;i<=n;i++)cin>>f[i];
for(int i=;i<=n;i++)cin>>c[i];
for(int i=;i<=n;i++)vec[f[i]].push_back(c[i]);
for(int i=;i<=n;i++)sort(vec[i].begin(),vec[i].end());
int M_P=1e9,M_POS=;
for(int i=;i<=n;i++)
{
if((int)vec[i].size()<M_P)
{
M_P=(int)vec[i].size();
M_POS=i;
}
}
int sl=;
for(int i=;i<=n;i++)if((int)vec[i].size()==M_P)sl++;
if(sl==n)
{
int Minn=1e9,Minnp=;
for(int i=;i<=n;i++)if((int)vec[i].size()>&&vec[i][]<Minn)Minn=vec[i][],Minnp=i;
vec[Minnp].push_back(0x3f3f3f3f);
}
else vec[M_POS].push_back(0x3f3f3f3f);
int Min=1e9;
for(int i=(int)vec[].size();i<n;i++)
{
vector<int>prem[],prr;
int NEED=i-(int)vec[].size();
for(int j=;j<=n;j++)prem[j]=vec[j];
int sum=;
for(int j=;j<=n;j++)
{
if((int)prem[j].size()>=i)
{
int need=(int)prem[j].size()-i+;
NEED-=need;
if(NEED<)goto e;
for(int k=;k<need;k++)sum+=prem[j][k];
for(int k=need;k<(int)prem[j].size();k++)prr.push_back(prem[j][k]);
}
else
{
for(int k=;k<(int)prem[j].size();k++)
prr.push_back(prem[j][k]);
}
}
if(NEED>)
{
sort(prr.begin(),prr.end());
for(int j=;j<NEED;j++)sum+=prr[j];
}
Min=min(Min,sum);
e:;
}
cout<<Min<<endl;
}
return ;
}

L.cpp

M.2337

已知Dick12岁,janepuff和spot相差s岁,yertle和puff相差p岁,yertle和spot相差y岁,Spot, Puff, Yertle和等于Dick,jane和,求Spot, Puff, Yertle的岁数。

那么由确定关系,设yertle为x岁,那么spot为x + y, puff为x + p然后与s进行比较。

#include<bits/stdc++.h>
using namespace std; int main()
{
int n,s,p,y,t;
cin>>n;
while(n--)
{
cin>>s>>p>>y>>t;
int sum=+t;
int temp=sum-y-p;
int x=temp/;
if(temp%==)
cout<<x+y<<" "<<x+p<<" "<<x<<endl;
else if(temp%==)
{
if(s+p==y)
cout<<x+y+<<" "<<x+p<<" "<<x<<endl;
else
cout<<x+y<<" "<<x+p+<<" "<<x<<endl;
}
else
cout<<x+y+<<" "<<x+p+<<" "<<x<<endl;
}
return ;
}

M.cpp

集训队日常训练20180513-DIV1的更多相关文章

  1. 集训队日常训练20181117 DIV2

    大佬们一顿操作猛如虎,拼命AC强啊 4262: 区间异或  Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal ...

  2. 集训队日常训练20181201 C 1003 : 种类数

    时间限制(普通/Java):2000MS/6000MS     内存限制:65536KByte总提交: 8            测试通过:5 描述 一共有 n个数,第 i 个数是 xi ,其中xi  ...

  3. 集训队日常训练20181201 E 1005 : 小蝌蚪

    时间限制(普通/Java):500MS/1500MS     内存限制:65536KByte总提交: 25            测试通过:5 描述 有 n 个装着小蝌蚪的水缸排成一排,你拥有一个无限 ...

  4. 集训队日常训练20181124 DIV2

    急急忙忙要出去比赛就拉了一场有点sb的题目 5202: 网络寻路  时间限制(普通/Java):1000MS/3000MS     内存限制:65536KByte总提交: 15            ...

  5. 集训队日常训练20181110 DIV2 题解及AC代码

    4375: 孪生素数  Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal Submit: 324       ...

  6. 集训队日常训练20180525-DIV2

    A.2295 求有多少素数对和等于n. 暴力. #include <bits/stdc++.h> using namespace std; int ss(int n) { ,a=sqrt( ...

  7. 集训队日常训练20180525-DIV1

    A.2805 N*M的图,每次浇水(X1,Y1)-(X2,Y2)围成的矩形,问最后有多少点被浇水了. 暴力. #include<bits/stdc++.h> using namespace ...

  8. 集训队日常训练20180518-DIV2

    A.3232 n个物品,换取要花积分,问刚好花完积分能换最大多少价值的物品. 多重背包. #include <bits/stdc++.h> using namespace std; ]; ...

  9. 集训队日常训练20180518-DIV1

    A.3583 n根木棍是否能分成相等两堆. 背包dp,首先求和sum,如果为偶数就说明不行,否则考虑做一个sum/2大小的背包. #include<bits/stdc++.h> using ...

随机推荐

  1. python2 和Python3 转unicode占位。

  2. form表单简易注册登陆

    注册页面: html <form action="updata.php" method="post" id="text_form"&g ...

  3. svn使用方法以及使用教程

    一.什么是svnSVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS. 二.svn的下载安装下载地址:https: ...

  4. .Net Email操作类

    using System; using System.Text; using System.Net.Mail; using System.Net; using System.Linq; using S ...

  5. Python2 Python3 urllib方法对应

    Python2 name Python3 nameurllib.urlopen() urllib.request.urlopen()urllib2.urlopen() urllib.request.u ...

  6. golang Linux下编译环境搭建

    1.下载golang1.4和1.10源码(1.4以后的版本都用1.4go编译安装,所以先安装1.4) 2.解压后我的目录结构是: /opt/xxx/golang |-------gopath     ...

  7. Selenium浏览器自动化测试使用(1)

    Selenium - 介绍 Selenium是一个开源的和便携式的自动化软件测试工具,用于测试Web应用程序有能力在不同的浏览器和操作系统运行.Selenium真的不是一个单一的工具,而是一套工具,帮 ...

  8. ubuntu 安装samba共享文件夹

    安装samba sudo apt-get install samba smbclient 配置samba sudo cp /etc/samba/smb.conf /etc/samba/smb.conf ...

  9. 廖雪峰Java10加密与安全-4加密算法-4密钥交换算法

    1DH算法 1.1.原根公式:g^i mod P 条件:1<g<P,0<i<P 原根:介于[1, p-1]之间的任意2个数i,j(p为素数,i≠j)的结果不相等,即 g^i m ...

  10. Python_day01——字符串

    https://www.cnblogs.com/A-FM/p/5691468.html def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 # 获 ...