------------7题弟弟,被各位半小时13题的大佬打惨了(滑稽)----------

签到题就不写了。

F :Moving On            (1247ms)

题意:给定大小为N的带点权,带边权的完全图,N<200。 然后Q次询问,每次给出(u,v,w),让你求在除了起点终点的其他途经点的点权都<=w的条件下的最短路。

思路:可以离线做的话,显然就是需要排序了。 然后想到floyd就是一个用点更新的最短路算法。 那么我们把floyd的第一层按点权排个序即可。 那么第k层的dis[i][j],就表示途经点都<=w[k]的最短路。 为了方便,这里所有的点权和询问的w都离散化了。 (比赛因为没有初始化WA了半天,哭)(网上看了其他人的写法大都是三维的,显然没必要,很明显是滚动的,在可以离线的情况下,第一维没什么用)。

#include<bits/stdc++.h>
#define pii pair<int,int>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
const int maxm=;
int mp[maxn][maxn],b[maxn],tot,ans[maxm];
struct in{
int u,v,w,id;
};
vector<in>G[maxn];
pii a[maxn];
int main()
{
int T,N,M,C=;
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&M);
rep(i,,N) scanf("%d",&a[i].first),a[i].second=i;
rep(i,,N) b[i]=a[i].first;
sort(b+,b+N+);
tot=unique(b+,b+N+)-(b+);
rep(i,,tot) G[i].clear();
rep(i,,N) a[i].first=lower_bound(b+,b+tot+,a[i].first)-b;
sort(a+,a+N+);
rep(i,,N) rep(j,,N) scanf("%d",&mp[i][j]);
rep(i,,M) {
in t;
scanf("%d%d%d",&t.u,&t.v,&t.w);
ans[i]=mp[t.u][t.v];
t.w=upper_bound(b+,b+tot+,t.w)-b;
t.w--; t.id=i;
G[t.w].push_back(t);
}
rep(k,,N) {
int tk=k; while(tk+<=N&&a[tk+].first==a[k].first) tk++;
rep(p,k,tk) {
rep(i,,N)
rep(j,,N){
int kk=a[p].second;
mp[i][j]=min(mp[i][j],mp[i][kk]+mp[kk][j]);
}
}
for(int i=;i<G[a[k].first].size();i++){
in t=G[a[k].first][i];
ans[t.id]=min(ans[t.id],mp[t.u][t.v]);
}
k=tk;
}
printf("Case #%d:\n",++C);
rep(i,,M) printf("%d\n",ans[i]);
}
return ;
}

G:Factories (1036ms)

题意:给定一个大小为N的无根树,让你选K个叶子,使得两两间距离和最短。 (N<1e5, K<100);

思路:这类题可能会想到换根DP,然后这里想了想没必要 。    如果有度数大于1的,它就可以作为根,然后就是一个树上背包题,而谁作为根,效果是一样的,所以没必要换根DP。    然后发现想不出O(NK)的写法,所以瞎交了一发O(NK^2)。 居然过了。 玄学。

update:这样实际的复杂度是O(NK)的。

参考:https://www.cnblogs.com/ouuan/p/BackpackOnTree.html

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
const ll inf=1LL<<;
int Laxt[maxn],Next[maxn<<],To[maxn<<],len[maxn<<],cnt;
int ind[maxn],rt,sz[maxn],K;
void add(int u,int v,int w){
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; len[cnt]=w;
}
ll dp[maxn][],ans;
void read(int &x){
x=; char c=getchar();
while(c>''||c<'') c=getchar();
while(c>=''&&c<='') x=x*+c-'',c=getchar();
}
void dfs(int u,int f)
{
sz[u]=; int leaf=; dp[u][]=;
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i]; if(v==f) continue;
leaf=; dfs(v,u);
for(int k=sz[u];k>=;k--){
for(int j=min(K-k,sz[v]);j>=;j--){
dp[u][k+j]=min(dp[u][k+j],dp[u][k]+dp[v][j]+1LL*(K-j)*j*len[i]);
}
}
sz[u]+=sz[v];
}
if(leaf) sz[u]=,dp[u][]=;
if(sz[u]>=K) ans=min(ans,dp[u][K]);
}
int main()
{
int T,N,C=,u,v,w;
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&K);
rep(i,,N) Laxt[i]=; cnt=;
rep(i,,N+) rep(j,,K) dp[i][j]=inf; ans=inf;
rep(i,,N) ind[i]=;
rep(i,,N-){
read(u); read(v); read(w);
add(u,v,w); add(v,u,w);
ind[u]++; ind[v]++;
}
if(N==||K<=) ans=;
else if(N==) ans=len[];
else {
rep(i,,N) if(ind[i]>) {
rt=i; break;
}
dfs(rt,);
}
printf("Case #%d: %lld\n",++C,ans);
}
return ;
}

I: Bubble Sort

题意:如果K轮冒泡排序后LIS>=N-1,则说这个排列是ok的,给次给出N和K,问有多少个是ok的。

思路:不难想到可以DP做。

(代码晚点再放。

K:Vertex Covers (1060ms)

题意:给定N点M边的无向图,每个点有点权。  点覆盖表示某个点集S{}覆盖了所有的边,其贡献是点权S之积。 现在让你求所有的贡献之和。N<36,保证无重边,自环。

思路:点覆盖的问题,而且N比较小,不难想到状压。  可以这里N最大为36,显然还需要一个折半枚举,然后想办法合并两边。

那么我们把点分为L,R两个集合。   那么边有三类: 1,两端点在L中; 2,两端点在R中; 3,两端点在L和R中各一个。

那么显然,对于1类边,两个端点至少一个要选;  对于2类边同理;  对于第3类边, 如果L中没选,那么R中必选,即补集的超集,而超集我们可以用高维前缀和搞定。  所以这题就完了。 (那些100ms跑出来的人都是神仙吧)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int a[maxn],sum[maxn],ltl[],ltr[],rtr[],Mod;
void MOD(int &x){ if(x>=Mod) x-=Mod;}
int main()
{
int T,N,M,u,v,C=;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&N,&M,&Mod);
rep(i,,N-) scanf("%d",&a[i]);
rep(i,,N-) ltl[i]=ltr[i]=rtr[i]=;
int L=(N+)/, R=N-L, ans=;
rep(i,,M){
scanf("%d%d",&u,&v);
u--, v--;
if(u>v) swap(u,v);
if(u<L){
if(v<L) ltl[u]|=(<<v);
else ltr[u]|=(<<(v-L));
}
else rtr[u]|=(<<(v-L));
}
rep(i,,(<<R)-){
int res=;
rep(j,,R-){
if(i&(<<j)) res=1LL*res*a[j+L]%Mod;
else {
res=res*((rtr[j+L]|i)==i);
if(!res) break;
}
}
sum[i]=res;
}
rep(i,,R-) {
rep(j,,(<<R)-) {
if(!(j&(<<i))) MOD(sum[j]+=sum[j|(<<i)]);
}
}
rep(i,,(<<L)-){
int res=,need=;
rep(j,,L-) {
if(i&(<<j)) res=1LL*res*a[j]%Mod;
else {
res=res*((ltl[j]|i)==i),need|=ltr[j];
if(!res) break;
}
}
MOD(ans+=1LL*res*sum[need]%Mod);
}
printf("Case #%d: %d\n",++C,ans);
}
return ;
}

L:Continuous Intervals (1075ms)

题意:给定长度为N的序列,求有多少个子区间,满足这个区间排序后,相邻的数相差<=1;

思路:即是问,有多少个区间满足max-min+1==cnt,max和min是区间最大最小值,cnt是区间种类数。

分治吗? 没法分,没法治。       启发式分治吗?没法找mid。

所以试一试暴力?    我们枚举右端点R,那么就是统计多少个L合法。  假设得到了[1,R-1]的所有信息,现在加入一个R进去,

1,可能会对某些区间的极值产生影响;        2,可能会对某个区间的cnt产生影响。

我们只需要维护好每个L点的信息,用来表示后缀的极值和cnt即可。

如何维护区间极值:线段树。

如何减少维护次数:单调队列+lazy。

对于cnt:影响的只有[laxt[a[R]]+1,R]这个区间。

所以综上,只需要维护三个lazy即可。 然后右移R,修改线段树,统计有多少个max-min+1=cnt,即max-min-cnt==-1的区间即可。

由于有三种变量,所以维护三个lazy会比较麻烦。 我们直接维护一个差值,这样可以统一,变成每次都是维护一个差值可以了。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int Mn[maxn],lazy[maxn],sum[maxn],a[maxn];
int q1[maxn],t1,q2[maxn],t2;
map<int,int>mp;
void build(int Now,int L,int R)
{
sum[Now]=R-L+; Mn[Now]=lazy[Now]=;
if(L==R) return ; int Mid=(L+R)>>;
build(Now<<,L,Mid);
build(Now<<|,Mid+,R);
}
void pushdown(int Now)
{
if(!lazy[Now]) return ;
Mn[Now<<]+=lazy[Now]; Mn[Now<<|]+=lazy[Now];
lazy[Now<<]+=lazy[Now]; lazy[Now<<|]+=lazy[Now];
lazy[Now]=;
}
void pushup(int Now)
{
Mn[Now]=min(Mn[Now<<],Mn[Now<<|]);
if(Mn[Now<<]==Mn[Now<<|]) sum[Now]=sum[Now<<]+sum[Now<<|];
else if(Mn[Now<<]<Mn[Now<<|]) sum[Now]=sum[Now<<];
else sum[Now]=sum[Now<<|];
}
void update(int Now,int L,int R,int l,int r,int v)
{
if(l>r) return ;
if(L==R) {
Mn[Now]+=v;
return ;
}
if(l<=L&&r>=R){
Mn[Now]+=v; lazy[Now]+=v;
return ;
}
int Mid=(L+R)>>; pushdown(Now);
if(l<=Mid) update(Now<<,L,Mid,l,r,v);
if(r>Mid) update(Now<<|,Mid+,R,l,r,v);
pushup(Now);
}
int main()
{
int T,N,C=; ll ans;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
rep(i,,N) scanf("%d",&a[i]);
build(,,N);
t1=t2=; ans=; mp.clear();
rep(i,,N){
update(,,N,i,i,-);
while(t1&&a[i]>=a[q1[t1]]){
update(,,N,q1[t1-]+,q1[t1],a[i]-a[q1[t1]]);
t1--;
}
q1[++t1]=i; while(t2&&a[i]<=a[q2[t2]]){
update(,,N,q2[t2-]+,q2[t2],a[q2[t2]]-a[i]);
t2--;
}
q2[++t2]=i; update(,,N,mp[a[i]]+,i-,-); mp[a[i]]=i;
ans+=sum[];
}
printf("Case #%d: %lld\n",++C,ans);
}
return ;
}

“2018宁夏邀请赛 ” 兼 “The 2019 Asia Yinchuan First Round Online Programming”的更多相关文章

  1. [The 2019 Asia Yinchuan First Round Online Programming] D Take Your Seat

    也许更好的阅读体验 \(\mathcal{Description}\) 原题链接 题目大意 该题目有两个问题 \(Task\ 1\),有\(n\)个人\(n\)个座位,每个人都有一个对应的座位,每个人 ...

  2. The 2019 Asia Yinchuan First Round Online Programming F. Moving On

    t题目链接:https://nanti.jisuanke.com/t/41290 思路:题目意思很容易想到floyd,但是由于危险度的限制,我们该怎么跑floyd呢. 一开始理解错题目了,以为u-&g ...

  3. The 2019 Asia Nanchang First Round Online Programming Contest

    传送门 A. Enju With math problem 题意: 给出\(a_1,\cdots,a_{100}\),满足\(a_i\leq 1.5*10^8\). 现在问是否存在一个\(pos\), ...

  4. The 2019 Asia Nanchang First Round Online Programming Contest C(cf原题,线段树维护矩阵)

    题:https://nanti.jisuanke.com/t/41350 分析:先将字符串转置过来 状态转移,因为只有5个状态,所以 i 状态到 j 状态的最小代价就枚举[i][k]->[k][ ...

  5. The 2019 Asia Nanchang First Round Online Programming Contest E. Magic Master

    题目链接:https://nanti.jisuanke.com/t/41352 题目意思还是好理解的,看过的人不多,感觉是被通过量吓到了.其实就是个水题,反向模拟就好了, 用队列模拟,反向模拟,它要放 ...

  6. The 2019 Asia Nanchang First Round Online Programming Contest B. Fire-Fighting Hero

    题目链接:https://nanti.jisuanke.com/t/41349 题意:有一个灭火英雄,和一个灭火团队,一个人与一个团队比较. 灭火英雄到其他灭火点的最短路最大值,与一个团队到其他灭火点 ...

  7. The 2019 Asia Nanchang First Round Online Programming Contest The Nth Item

    The Nth Item 思路: 先用特征根法求出通向公式,然后通向公式中出现了\(\sqrt{17}\),这个可以用二次剩余求出来,然后可以O(\(log(n)\))求出. 但是还不够,我们先对\( ...

  8. H. The Nth Item(The 2019 Asia Nanchang First Round Online Programming Contest)

    题意:https://nanti.jisuanke.com/t/41355 给出N1,计算公式:A=F(N)Ni=Ni-1 ^ (A*A),F为类斐波那契需要矩阵快速幂的递推式. 求第k个N. 思路: ...

  9. E.Magic Master(The 2019 Asia Nanchang First Round Online Programming Contest)

    直接模拟orhttps://blog.csdn.net/liufengwei1/article/details/100643831

随机推荐

  1. Keras 使用过程问题汇总

    以下是Keras 使用过程出现的一些问题: (1)Keras 后端选择问题 一开始是选用的Theano,结果迭代一轮所花时间很长: 后面改用:TensorFlow作为后端,结果果然变快了: 改完Ten ...

  2. SSM 整合配置

    目录 1. Maven : pox.xml 2. Web container : web.xml 3. Spring context : dbconfig.properties + applicati ...

  3. TPad需求和迭代

    需求和迭代最主要的区别是什么

  4. java解析复杂的json字符串

    Java解析Json字符串--复杂对象(方法一)   { "name": "三班", "students": [ { "age&q ...

  5. Git系列 —— github提交一个空目录

    转载自github提交一个空目录 github默认不上传空目录,有的时候需要空目录来保持程序的结构. 两种场景 1.始终保持空目录,即时里面有文件,也全部忽略掉. 建立一个.gitignore文件放到 ...

  6. Elasticsearch常见用法-入门

    前台启动 默认是只有本地可以访问 ./bin/elasticsearch 远程访问 修改elasticsearch.yml,把network.host(注意配置文件格式不是以 # 开头的要空一格, : ...

  7. syntax error near unexpected token 脚本报错误解决

    hadoop老师给了一个shell文件,在windows里面瞅了一眼然后在ubuntu环境下运行就报错了.看了一些博客,用vim -b filename查看的时候发现每一行的末尾都多了一个^M.... ...

  8. java什么是构造方法

    构造方法 一.构造方法的特点 (1)每当创建给定类的实例时就调用的方法 (2)与类同名,但没有返回类型 (3)Java 为对象分配内存,初始化实例变量并调用构造方法 (4)两种构造方法 1.参数化构造 ...

  9. jQuery实现form表单基于ajax无刷新提交方法详解

    本文实例讲述了jQuery实现form表单基于ajax无刷新提交方法.分享给大家供大家参考,具体如下: 首先,新建Login.html页面: <!DOCTYPE html PUBLIC &quo ...

  10. Spring Security OAuth2.0 - AuthorizationServer和ResourceServer分离

    <Spring Security实现OAuth2.0授权服务 - 基础版>和<Spring Security实现OAuth2.0授权服务 - 进阶版>两篇文章中介绍如何搭建OA ...