------------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. ORM之Entity Framework(EF)

    ORM之Entity Framework(EF) 一.下载安装: nuget 搜索Entity Framework安装 EntityFramework.Extension是个扩展库根据需要安装 二.使 ...

  2. rpm续

    一.安装源码包 安装源码包通常须要一下三步: (1) ./configure. 这步可以定制功能,加上相应 的选项即可,具体有什么选项可以通过命令./configure help来查看.这一步会 自动 ...

  3. html5点击input没有出现光标完美解决方案

    html5点击input没有出现光标完美解决方案 <pre> <input type="text" placeholder="输入姓名" cl ...

  4. PHP重命名文件夹下的文件后缀名

    PHP重命名文件夹下的文件后缀名<pre> public function zhuanhouzuiming(){ $lujings='upload/'; $filesnames = sca ...

  5. LeetCode 717. 1比特与2比特字符(1-bit and 2-bit Characters)

    717. 1比特与2比特字符 LeetCode717. 1-bit and 2-bit Characters 题目描述 有两种特殊字符.第一种字符可以用一比特0来表示.第二种字符可以用两比特(10 或 ...

  6. Android开发遇到的一些小问题

    1.文件下载时,默认只能用https,怎么用http协议: 在Manifest.xml文件中增加一个配置项: android:usesCleartextTraffic="true" ...

  7. Hystrix实现ThreadLocal上下文的传递 转

    springcloud微服务中, 服务间传输全局类参数,如session信息等. 一.问题背景 Hystrix有2个隔离策略:THREAD以及SEMAPHORE,当隔离策略为 THREAD 时,是没办 ...

  8. 查看电脑已保存的wifi及密码

    1. 查看以保存的wifi名称  打开cmd(win+r) #查看已保存WiFi名称 netsh wlan show profiles 2. 查看已保存的wifi的密码 netsh wlan show ...

  9. k8s的学习

    20191123 开始重头再学一遍k8 一 K8S的组件介绍

  10. maven添加本地包命令mvn install:install-file

    mvn install:install .jar -Dfile:要注册的jar,绝对路径