四连测Day4
四连爆炸
卡我常数
好像被AluminumGod拉到了创客...哇我这个天天爆炸的水平可能会被其他三位dalao吊起来打
orz Edmond-Karp_XiongGod
orz Deidara_WangGod
orz Small_ChickenGod
T1 树上有一些关键点,求包含i个关键点的联通块数,0<=i<=m
n,m<=1000
树形dp,强行证明复杂度
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) x=x*+ch-'',ch=getchar();
return x*f;
}
const int maxn = ,mod = ;
vector<int> G[maxn];
int n,m;int a[maxn];
int state;
LL f[maxn][maxn],size[maxn],ans[maxn];
inline void dp(int x,int fa)
{
size[x] = ;
if(a[x] == )f[x][] = ;
else f[x][] = ;
for(auto to : G[x])
{
if(to == fa)continue;
dp(to,x);size[x] += size[to];
for(int i=size[x];i>=;i--)
{
for(int j=;j<=i && j<=size[to];j++)
(f[x][i] += 1ll * f[to][j] * f[x][i - j]) %= mod;
}
}
for(int i=;i<=size[x];i++)(ans[i] += f[x][i]) %= mod;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n = read(),m = read();
for(int i=;i<=m;i++)a[read()] = ;
for(int i=;i<n;i++)
{
int u = read(),v = read();
G[u].push_back(v);G[v].push_back(u);
}
dp(,);
for(int i=;i<=m;i++)printf("%lld ",ans[i]);
}
(虽然不是严格n^2但也卡不到n^3 比标算慢一点)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define MAXN 131072
#define MOD 998244353
using namespace std;
inline int read()
{
int x=,t=,c;
while(!isdigit(c=getchar()))if(c=='-')t=-;
while(isdigit(c))x=x*+c-'',c=getchar();
return x*t;
}
int first[],nxt[],targ[],cnte=;
bool special[];
int ans[];
int dp[][],cntd[];
int poly[];
void AddEdge(int u,int v)
{
targ[cnte]=v;nxt[cnte]=first[u];first[u]=cnte++;swap(u,v);
targ[cnte]=v;nxt[cnte]=first[u];first[u]=cnte++;
}
void DP(int x,int Fa)
{
if(special[x])
{
dp[x][]=;cntd[x]=;
}
else
{
dp[x][]=;cntd[x]=;
}
for(int i=first[x];i;i=nxt[i])
{
if(targ[i]==Fa)continue;
int y=targ[i];
DP(y,x);
for(int i=;i<cntd[x]+cntd[y]-;i++)poly[i]=;
for(int i=;i<cntd[x];i++)
for(int j=;j<cntd[y];j++)
(poly[i+j]+=(long long)dp[x][i]*dp[y][j]%MOD)%=MOD;
cntd[x]+=cntd[y]-;
for(int i=;i<cntd[x];i++)dp[x][i]=poly[i];
}
for(int i=;i<cntd[x];i++)(ans[i]+=dp[x][i])%=MOD;
dp[x][]++;dp[x][]%=MOD;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
int n=read(),m=read();
for(int i=;i<m;i++)special[read()]=;
for(int i=;i<n;i++)AddEdge(read(),read());
DP(,);
for(int i=;i<=m;i++)printf("%d%c",ans[i],i==m?'\n':' ');
}
(集训队dalao的标算)
T2
每个机器人对每个零件有一个需求度,现在你有$n$个机器人$m$个零件,第$i$个机器人需要$ki$个零件,求所有机器人需求度和的最大值
费用流
S->机器人 caps = ki,cost = 0
机器人->零件 caps = 1,cost = 需求度
零件->T caps = 1,cost = 0
然后跑最大费用最大流
#include<bits/stdc++.h>
using namespace std;
const int maxn = * * ;
long long ans;//此处ans保存费用
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) x=x*+ch-'',ch=getchar();
return x*f;
}
int n,m,s,t;
int first[maxn],to[maxn],nx[maxn],caps[maxn],cost[maxn],cnt=-;
int vis[maxn],dis[maxn];
deque<int> dq;
inline void add(int u,int v,int w,int c)
{
to[++cnt]=v;
nx[cnt]=first[u];
first[u]=cnt;
caps[cnt]=w;
cost[cnt]=c;
}
inline void ins(int u,int v,int w,int c){add(u,v,w,c);add(v,u,,-c);}
inline int afps(int s,int t)//反向spfa
{
memset(vis,,sizeof(vis));
memset(dis,,sizeof(dis));
dis[t]=;vis[t]=;
dq.clear();
dq.push_back(t);
while(!dq.empty())
{
int now=dq.front();dq.pop_front();
for(int i=first[now];i>-;i=nx[i])
if(caps[i^] && dis[to[i]]>dis[now]-cost[i])
{
dis[to[i]]=dis[now]-cost[i];
if(!vis[to[i]])
{
vis[to[i]]=;
if(!dq.empty() && dis[to[i]]<dis[dq.front()])dq.push_front(to[i]);
else dq.push_back(to[i]);
}
}
vis[now]=;
}
return dis[s]<;
}
inline int dfs(int u,int flow)
{
if(u==t){vis[t]=;return flow;}
int used=,tmp;vis[u]=;
for(int i=first[u];i>-;i=nx[i])
if(!vis[to[i]] && caps[i] && dis[u]-cost[i]==dis[to[i]])
{
tmp=dfs(to[i],min(caps[i],flow-used));
if(tmp)ans+=1ll*tmp*cost[i],caps[i]-=tmp,caps[i^]+=tmp,used+=tmp;
if(used==flow)break;
}
return used;
}
inline int zkw()
{
long long maxflow=;
while(afps(s,t))
{
vis[t]=;
while(vis[t])
{
memset(vis,,sizeof(vis));
maxflow+=(long long)dfs(s,);
}
}
return maxflow;
}
int main()
{
freopen("robot.in","r",stdin);
freopen("robot.out","w",stdout);
memset(nx,-,sizeof nx);memset(first,-,sizeof first);
n=read(),m=read();s = ;t = n + m + ;
for(int i=;i<=n;i++)
{
int a = read();
ins(s,i,a,);
}
for(int i=;i<=m;i++)ins(i + n,t,,);
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
int a = read();
ins(i,j + n,,-a);
}
}
zkw();
printf("%d",-ans);
}
需要注意的是这道题图很稠密,EK被卡成了暴力分
T3
有一维空间内$n$个点,编号从$1$到$n$,编号为$i$的点坐标为$x_i$。
现在,请选出编号连续的一些点,使得被选出的所有点到某一点的距离和的最小值不超过一正
整数$m$,问最多选出多少点?
$O(nlog^2n)$的做法:(卡常的出题人嘤嘤嘤qwq)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{
int x = ,f = ;char ch = getchar();
while(!isdigit(ch)){if(ch == '-') f = -;ch = getchar();}
while(isdigit(ch)) x = x * + ch - '',ch = getchar();
return x * f;
}
const int maxpos = ;
int n,m;
int res;
int va[maxpos * + ];
int size[maxpos * + ];
int a[];
#define ls (x << 1)
#define rs ((x << 1) | 1)
inline void Insert(int x,int l,int r,int val,int f)
{
if(l == r){size[x] += f;va[x] += (l * f);return;}
int mid = (l + r) >> ;
if(val <= mid) Insert(ls,l,mid,val,f);
else Insert(rs,mid + ,r,val,f);
va[x] = va[ls] + va[rs];
size[x] = size[ls] + size[rs];
}
inline int kth(int x,int l,int r,int val)
{
if(l == r)return l;
int mid = (l + r) >> ;
if(val <= size[ls]) return kth(ls,l,mid,val);
else return kth(rs,mid + ,r,val - size[ls]);
}
inline int query(int x,int l,int r,int L,int R)
{
if(L<= l && R >= r){res += size[x];return va[x];}
int mid = (l + r) >> ;
int ret = ;
if(L <= mid)ret += query(ls,l,mid,L,R);
if(R > mid)ret += query(rs,mid + ,r,L,R);
return ret;
}
inline int check(int mid)
{
memset(va,,sizeof(va));memset(size,,sizeof(size));
for(int i = ;i <= mid;i++)Insert(,,maxpos,a[i],);
int pos = kth(,,maxpos,(mid + ) >> );
res = ;
int ans = query(,,maxpos,,pos);
if( ( ( res * pos ) - ans ) + ( va[] - ans) - ( (mid - res ) * pos) <= m) return ;//!!!
for(int i = mid + ;i<=n;i++)
{
Insert(,,maxpos,a[i - mid], - );
Insert(,,maxpos,a[i],);
pos = kth(,,maxpos,(mid + ) >> );
res = ;
ans = query(,,maxpos,,pos);
if( ( ( res * pos ) - ans ) + ( va[] - ans) - ( (mid - res ) * pos) <= m) return ;//!!!
}
return ;
}
int main()
{
freopen("choose.in","r",stdin);
freopen("choose.out","w",stdout);
n = read(),m = read();
for(int i = ;i <= n;i++)a[i] = read();
int l = ,r = n,ans;
while(l <= r)
{
int mid = (l + r) >> ;
if(check(mid)) {l = mid + ;ans = mid;}
else r = mid - ;
}
printf("%d\n",ans);
}
$O(nlogn)$的做法:(放份好看的)
。。。还是来写一下标算的做法吧
可以知道到“某一点距离和的最小值”一定是这几个点的中位数
维护一个滑动窗口,每次用平衡树查询窗口内的答案,看合不合法,处理出以每个点开头/结尾的滑窗的最长长度即可
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#include<set>
#define MAXN 100100
#define MAXX 1001000
#define ll long long
#define inf 2139062143
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,l,ans,g[MAXN],val[MAXX<<],maxn;
ll sum[MAXX<<];
void mdf(int k,int l,int r,int x,int p)
{
if(l==r) {sum[k]+=p*x,val[k]+=p;return ;}
int mid=(l+r)>>;
if(x<=mid) mdf(k<<,l,mid,x,p);
else mdf(k<<|,mid+,r,x,p);
sum[k]=sum[k<<]+sum[k<<|],val[k]=val[k<<]+val[k<<|];
}
ll Ask(int k,int l,int r,int x)
{
if(l==r) return val[k]*maxn+l;
int mid=(l+r)>>;
if(val[k<<]>=x) return Ask(k<<,l,mid,x);
else return Ask(k<<|,mid+,r,x-val[k<<]);
}
ll query(int k,int l,int r,int a,int b)
{
if(a>b) return ;
if(l==a&&r==b) return sum[k];
int mid=(l+r)>>;
if(b<=mid) return query(k<<,l,mid,a,b);
else if(a>mid) return query(k<<|,mid+,r,a,b);
else return query(k<<,l,mid,a,mid)+query(k<<|,mid+,r,mid+,b);
}
int lft(int k,int l,int r,int a,int b)
{
if(a>b) return ;
if(l==a&&r==b) return val[k];
int mid=(l+r)>>;
if(b<=mid) return lft(k<<,l,mid,a,b);
else if(a>mid) return lft(k<<|,mid+,r,a,b);
else return lft(k<<,l,mid,a,mid)+lft(k<<|,mid+,r,mid+,b);
}
ll calc(int x)
{
if(x==l) return ;
if(x-l==) return abs(g[x]-g[l]);
ll t=(x-l+)/+,k=Ask(,,maxn,t),lv=lft(,,maxn,,k%maxn-),q= k/maxn+*lv-x+l-;k%=maxn;
return query(,,maxn,k+,maxn)-query(,,maxn,,k-)+q*k;
}
int main()
{
freopen("choose.in","r",stdin);
freopen("choose.out","w",stdout);
n=read(),m=read();
for(int i=;i<=n;i++) g[i]=read(),maxn=max(maxn,g[i]);
for(int i=l=;i<=n;i++)
{
mdf(,,maxn,g[i],);
while(calc(i)>m) {mdf(,,maxn,g[l],-);l++;}
ans=max(ans,i-l+);
}
printf("%d",ans);
}
出题人为了卡我的常,甚至使用了前两题开O2这题临时不开的技巧...
嘤
四连测Day4的更多相关文章
- 【2018.8.10】四连测day4 题解
T1:给出一棵 $n$ 个节点的无根树,其中 $m$ 个节点是特殊节点,求对于任意 $i ∈ [0, m]$,包含 $i$ 个特殊节点的联通块个数$\mod 998244353$. $1<=n, ...
- 四连测总结(XYX)
目录 成绩 总结 事后... 成绩 telephonewire monkey 总分 0 56 56 cowjog guard path temperature 总分 0 40 0 68 108 cba ...
- 正睿 2018 提高组十连测 Day4 T3 碳
记'1'为+1,'0'为-1; 可以发现 pre[i],suf[i]分别为前/后缀和 a[i]=max(pre[l.....i]); b[i]=max(suf[i+1....r]); ans=max( ...
- 四连测Day3
题目链接:https://pan.baidu.com/s/1_vsHfMI_qO-9IDxmFLkHfg 密码: uza8 T1: 小奥的一笔画,判连通性,查奇偶点即可 #include<ios ...
- 四连测Day2
题目:链接: https://pan.baidu.com/s/1ef_9hGBhczW0B4dz5IUKmw 密码: qgjy T1: hash后直接二分查询即可 #include<iostre ...
- 四连测Day1
题目:链接: https://pan.baidu.com/s/163ycV64ioy7uML7AvRDTGw 密码: p86i T1: 倍增求LCA,minn数组记录最小值 #include<i ...
- (四连测)滑雪场的高度差题解---二分 + 搜索---DD(XYX)的博客
滑雪场的高度差 时间限制: 1 Sec 内存限制: 128 MB 题目描述 滑雪场可以看成M x N的网格状山地(1 <= M,N <= 500),每个网格是一个近似的平面,具有水平高度 ...
- STM32—TIMx实现编码器四倍频
文章目录 一.储备知识 二.TIMx的编码器模式介绍 1.计数边沿设置 2.选择极性和使能 3.使能 4.计数方向 三.代码部分 一.储备知识 通过STM32的定时器编码器接口模式对编码器进行四倍频, ...
- Android支付接入(七):Google In-app-Billing
前段时间有事请耽搁了,今天跟大家一起看下Google的in-app Billing V3支付. 如果没有Google Play此处附上安装Google Play的一键安装器的链接(需要Root权 ...
随机推荐
- SQLServer理解copyonly备份操作
Always在添加数据库的过程中如果同步首选项选择的是“完整”,那么就会在主副本上执行copyonly的完整备份和日志备份在辅助副本上执行还原操作,也正是这个操作让我对copyonly有了新的理解.接 ...
- ALLEGRO修改位号回注ORCAD原理图
资料:ALLEGRO修改位号回注ORCAD原理图 https://wenku.baidu.com/view/54e221e114791711cd7917e2.html?re=view
- CentOS 5.5安装SVN(Subversion)
检查已安装版本 #检查是否安装了低版本的SVN[root@localhost /]# rpm -qa subversion #卸载旧版本SVN[root@localhost modules]# yum ...
- Spring Cloud(十三):Spring Cloud Sleuth服务链路追踪(zipkin)(转)
这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件. 一.简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案, ...
- 兔子--改动Android Studio的快捷键,改动成eclipse的快捷键
仅仅须要2步 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzQyNTUyNw==/font/5a6L5L2T/fontsize/400/fill ...
- client交互技术简单介绍
随着网络应用的不断丰富,client交互技术也如雨后春笋一般,遍地开花. 正是这些技术的支持,我们的互联网世界变得更加丰富多彩.一个浏览器上.不用说是简单的动画效果,就是一个Office应用也能顺畅的 ...
- C#中判断某个值是否存在于枚举
我有一个枚举类型: #region -酒的种类- public enum WineType { 白酒 = 3, 葡萄酒 = 4, 洋酒 = 5, 老年陈酒 = 16, 啤酒 = 17 } #endre ...
- 在linux系统中I/O 调度的选择 (转)
I/O 调度算法再各个进程竞争磁盘I/O的时候担当了裁判的角色.他要求请求的次序和时机做最优化的处理,以求得尽可能最好的整体I/O性能. 在linux下面列出4种调度算法 CFQ (Completel ...
- iOS开发入门
https://github.com/qinjx/30min_guides/blob/master/ios.md 任何C源程序,不经修改,即可通过Objective-C编译器成功编译 Objectiv ...
- 10 redis--频道发布与消息订阅
消息订阅 使用办法: 订阅端: Subscribe 频道名称 发布端: publish 频道名称 发布内容 客户端例子: redis 127.0.0.1:6379> subscribe news ...