集训队日常训练20180513-DIV1
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的更多相关文章
- 集训队日常训练20181117 DIV2
大佬们一顿操作猛如虎,拼命AC强啊 4262: 区间异或 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal ...
- 集训队日常训练20181201 C 1003 : 种类数
时间限制(普通/Java):2000MS/6000MS 内存限制:65536KByte总提交: 8 测试通过:5 描述 一共有 n个数,第 i 个数是 xi ,其中xi ...
- 集训队日常训练20181201 E 1005 : 小蝌蚪
时间限制(普通/Java):500MS/1500MS 内存限制:65536KByte总提交: 25 测试通过:5 描述 有 n 个装着小蝌蚪的水缸排成一排,你拥有一个无限 ...
- 集训队日常训练20181124 DIV2
急急忙忙要出去比赛就拉了一场有点sb的题目 5202: 网络寻路 时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte总提交: 15 ...
- 集训队日常训练20181110 DIV2 题解及AC代码
4375: 孪生素数 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 324 ...
- 集训队日常训练20180525-DIV2
A.2295 求有多少素数对和等于n. 暴力. #include <bits/stdc++.h> using namespace std; int ss(int n) { ,a=sqrt( ...
- 集训队日常训练20180525-DIV1
A.2805 N*M的图,每次浇水(X1,Y1)-(X2,Y2)围成的矩形,问最后有多少点被浇水了. 暴力. #include<bits/stdc++.h> using namespace ...
- 集训队日常训练20180518-DIV2
A.3232 n个物品,换取要花积分,问刚好花完积分能换最大多少价值的物品. 多重背包. #include <bits/stdc++.h> using namespace std; ]; ...
- 集训队日常训练20180518-DIV1
A.3583 n根木棍是否能分成相等两堆. 背包dp,首先求和sum,如果为偶数就说明不行,否则考虑做一个sum/2大小的背包. #include<bits/stdc++.h> using ...
随机推荐
- VS2010-MFC(对话框:模态对话框及其弹出过程)
转自:http://www.jizhuomi.com/software/160.html 一.模态对话框和非模态对话框 Windows对话框分为两类:模态对话框和非模态对话框. 模态对话框是这样的对话 ...
- SPSS科普 | 统计描述
SPSS科普 | 统计描述 统计描述的目的就是了解数据的基本特征和分布规律,为进一步合理地选择统计方法提供依据.常用的有Frequencies.Descriptives 和Explore过程. 一.F ...
- WhaleCTF之隐写-Find
WhaleCTF之隐写-Find 前往题目 图片保存到本地,用Stegsolve打开图片 找到二维码 用微信或qq扫描,得到flag~
- java代码优化写法1(转摘)
源文地址:https://blog.csdn.net/qq_15766297/article/details/70503222 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修 ...
- [原创]mysql 5.6安装配置,主从分离,读写分离简单教程
文章中参考使用了多个博客的资料,汇总而成!其流程准确性被人亦本人实践! https://blog.csdn.net/qq_35206261/article/details/81321201 https ...
- fwt优化+树形DP HDU 5909
//fwt优化+树形DP HDU 5909 //见官方题解 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ #include <bits/ ...
- CentOS使用rpm离线安装mariadb
本文不再更新,可能存在内容过时的情况,实时更新请移步原文地址:CentOS使用rpm离线安装mariadb: 环境: CentOS Linux release 7.6.1810 (Core) mari ...
- React学习整理
React介绍 React设计思想及其独特,属于革命性创新,性能出众,代码逻辑却非常简单. 库(library):小而巧,库只提供了特定的api.优点是船小好调头,可以很方便的从一个库切换到另外的库, ...
- Gym-102141E
https://vjudge.net/problem/Gym-102141E 用set乱搞 #include<iostream> #include<cstdio> #inclu ...
- hdu1527
hdu1527两堆博弈模型,威佐夫博弈 #include<iostream> #include<cstdio> #include<queue> #include&l ...