https://www.nowcoder.com/acm/contest/27#question
A-凌波微步
LIS恐成最大输家,无力吐槽 = =
B-C水题
D-经商
小d是一个搞房地产的土豪。每个人经商都有每个人经商的手段,当然人际关系是需要放在首位的。
小d每一个月都需要列出来一个人际关系表,表示他们搞房地产的人的一个人际关系网,但是他的精力有限,对应他只能和能够接触到的人交际。比如1认识2,2认识3,那么1就可以接触3进行交际,当然1和2也可以交际。
小d还很精明,他知道他和谁交际的深获得的利益大,接下来他根据自己的想法又列出来一个利益表,表示他和这些人交际需要耗用多少精力,能够获得的利益值为多少。
小d想知道,他在精力范围内,能够获得的利益值到底是多少。
设定小d自己的编号为1.并且对应一个人的交际次数限定为1.
输入描述:
本题包含多组输入,第一行输入一个数t,表示测试数据的组数
每组数据的第一行输入三个数,N,M,C,表示这个人际关系网一共有多少个人,关系网的关系数,以及小d的精力值
接下来N-1行,每行两个数ai,bi。这里第i行表示和编号为i+1的人认识需要花费ai的精力,能够获得的利益值为bi。
再接下来M行,每行两个数x,y,表示编号为x的人能够和编号为y的人接触
t<=50
2<=N<=10000
1<=M<=10*N
1<=ai,bi<=10
1<=C<=500
1<=x,y<=N
输出描述:
输出包含一行,表示小d能够获得的最大利益值
示例1
输入
1 5 3 7 5 10 3 2 4 3 1 100 1 2 2 3 1 4
输出
10
并查集统计出1所有能接触到的人+背包求解最优值
1 #include<bits/stdc++.h> 2 using namespace std; 3 int f[10005],dp[550]; 4 int getf(int v){return f[v]==v?v:f[v]=getf(f[v]);} 5 struct node 6 { 7 int a,b; 8 }P[10005],Q[10005]; 9 int main() 10 { 11 int T,N,M,C,i,j,k,x,y; 12 scanf("%d",&T); 13 while(T--){int sq=0; 14 memset(dp,0,sizeof(dp)); 15 scanf("%d%d%d",&N,&M,&C); 16 for(i=1;i<=N;++i) f[i]=i; 17 for(i=2;i<=N;++i) 18 { 19 scanf("%d%d",&P[i].a,&P[i].b); 20 } 21 for(i=1;i<=M;++i) 22 { 23 scanf("%d%d",&x,&y); 24 int fx=getf(x),fy=getf(y); 25 if(fx!=fy){ 26 f[fx]=fy; 27 } 28 } 29 for( i=1;i<=N;++i) f[i]=getf(i); 30 int root=f[1]; 31 for(i=2;i<=N;++i) 32 { 33 if(f[i]==root){ 34 Q[++sq]=P[i]; 35 } 36 } 37 for(i=1;i<=sq;++i) 38 { 39 for(j=C;j>=Q[i].a;--j) 40 dp[j]=max(dp[j],dp[j-Q[i].a]+Q[i].b); 41 } 42 cout<<dp[C]<<endl; 43 } 44 return 0; 45 }
F-苦逼的单身狗
尺取法,枚举左边界,指定情况出现时再指定情况未消失时不断右移左边界并统计数量。
1 #include<bits/stdc++.h> 2 using namespace std; 3 char s[100005]; 4 int vis[5]; 5 int zh[30]; 6 #define inf 0x3f3f3f3f 7 int main() 8 { 9 int t,n,m,i,j,k; 10 zh['L']=1; 11 zh['O']=2; 12 zh['V']=3; 13 zh['E']=4; 14 cin>>t; 15 while(t--){ 16 cin>>s; 17 memset(vis,0,sizeof(vis)); 18 int len=strlen(s); 19 long long ans=0; 20 int cur=0; 21 for(i=0;i<len;++i) 22 { 23 k=zh[s[i]]; 24 if(k){ 25 vis[k]++; 26 } 27 while(cur<=i&&vis[4]&&vis[1]&&vis[2]&&vis[3]){ 28 ans+=(long long )len-i;//cout<<len-i<<endl; 29 if(zh[s[cur]]) vis[zh[s[cur]]]--; 30 cur++; 31 } 32 } 33 printf("%lld ",ans); 34 } 35 return 0; 36 }
H-布置会场
矩阵幂裸题。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define LL long long 7 LL M=1000000007; 8 9 struct Matrix { 10 long long a[2][2]; 11 Matrix() { 12 memset(a, 0, sizeof(a)); 13 } 14 Matrix operator * (const Matrix y) { 15 Matrix ans; 16 for(int i = 0; i <= 1; i++) 17 for(int j = 0; j <= 1; j++) 18 for(int k = 0; k <= 1; k++) 19 ans.a[i][j] += a[i][k]*y.a[k][j]; 20 for(int i = 0; i <= 1; i++) 21 for(int j = 0; j <= 1; j++) 22 ans.a[i][j] %= M; 23 return ans; 24 } 25 void operator = (const Matrix b) { 26 for(int i = 0; i <= 1; i++) 27 for(int j = 0; j <= 1; j++) 28 a[i][j] = b.a[i][j]; 29 } 30 }; 31 32 int solve(long long x) { 33 Matrix ans, trs; 34 ans.a[0][0] = ans.a[1][1] = 1; 35 trs.a[0][0] = trs.a[1][0] = trs.a[0][1] = 1; 36 while(x) { 37 if(x&1) 38 ans = ans*trs; 39 trs = trs*trs; 40 x >>= 1; 41 } 42 return ans.a[0][0]; 43 } 44 45 int main() { 46 long long n; 47 int t; 48 cin>>t; 49 while(t--){ 50 scanf("%lld", &n); 51 cout << solve(n) << endl; 52 } 53 return 0; 54 }
I-旅行
最短路+思维。
题目很显然就是求最大化的{任意有两条最短路连接的三个点中的这两条最短路径长度和},其中三个点互不相等。
首先我们要求出任意两点间的最短路这是肯定的,有N^3的floyd或是N*N*log(N)的dij,前者肯定炸了。对于后面的找这三个点的过程一直想的是N*N*N,这样的话无论最短路算法在再优化也会T,比赛时迫于时间
直接暴力了个floyd直接炸了。
其实找点用不到这么麻烦,题目求得时最大化的,三个点显然只有两条最短路,我们枚举1-n作为中转点,没次找到中转点对于其他点最大的两条最短路更新答案就好了。这样找的复杂度就降到了N^2不会T了。
好题。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define inf 0x3f3f3f3f 4 struct Edge 5 { 6 int to,w,next; 7 }e[2010]; 8 int first[1010],cnt; 9 struct node 10 { 11 int u,w; 12 bool operator<(const node& t)const{ 13 return w>t.w; 14 } 15 }; 16 void add(int u,int v,int w) 17 { 18 e[cnt].to=v; 19 e[cnt].w=w; 20 e[cnt].next=first[u]; 21 first[u]=cnt++; 22 } 23 int d[1005][1005]; 24 bool vis[1005]; 25 void dij(int u,int n) 26 { 27 priority_queue<node>Q; 28 node t1,t2; 29 memset(vis,0,sizeof(vis)); 30 d[u][u]=0; 31 Q.push(node{u,0}); 32 while(!Q.empty()){ 33 t1=Q.top(); 34 Q.pop(); 35 if(vis[t1.u]) continue; 36 vis[t1.u]=1; 37 for(int i=first[t1.u];i+1;i=e[i].next){ 38 if(d[u][e[i].to]>d[u][t1.u]+e[i].w){ 39 d[u][e[i].to]=d[u][t1.u]+e[i].w; 40 Q.push(node{e[i].to,d[u][e[i].to]}); 41 } 42 } 43 } 44 } 45 int main() 46 { 47 int t,n,m,i,j,k,u,v,w; 48 cin>>t; 49 while(t--){ 50 cin>>n>>m; 51 memset(first,-1,sizeof(first)); 52 memset(d,inf,sizeof(d)); 53 cnt=0; 54 for(i=1;i<=m;++i) 55 { 56 scanf("%d%d%d",&u,&v,&w); 57 add(u,v,w); 58 add(v,u,w); 59 } 60 for(i=1;i<=n;++i) dij(i,n); 61 int ans=-1; 62 for(i=1;i<=n;++i) 63 { 64 int t1=-1,t2=-1,maxn=0; 65 for(j=1;j<=n;++j) 66 { 67 if(d[i][j]!=inf&&d[i][j]>maxn){ 68 maxn=d[i][j]; 69 t1=j; 70 } 71 } 72 maxn=0; 73 for(j=1;j<=n;++j) 74 { 75 if(j!=t1&&d[i][j]!=inf&&d[i][j]>maxn){ 76 maxn=d[i][j]; 77 t2=j; 78 } 79 } 80 if(t1!=-1&&t2!=-1){ 81 ans=max(ans,d[i][t1]+d[i][t2]); 82 } 83 } 84 printf("%d ",ans); 85 } 86 return 0; 87 }