四连爆炸

卡我常数

好像被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的更多相关文章

  1. 【2018.8.10】四连测day4 题解

    T1:给出一棵 $n$ 个节点的无根树,其中 $m$ 个节点是特殊节点,求对于任意 $i ∈ [0, m]$,包含 $i$ 个特殊节点的联通块个数$\mod 998244353$. $1<=n, ...

  2. 四连测总结(XYX)

    目录 成绩 总结 事后... 成绩 telephonewire monkey 总分 0 56 56 cowjog guard path temperature 总分 0 40 0 68 108 cba ...

  3. 正睿 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( ...

  4. 四连测Day3

    题目链接:https://pan.baidu.com/s/1_vsHfMI_qO-9IDxmFLkHfg 密码: uza8 T1: 小奥的一笔画,判连通性,查奇偶点即可 #include<ios ...

  5. 四连测Day2

    题目:链接: https://pan.baidu.com/s/1ef_9hGBhczW0B4dz5IUKmw 密码: qgjy T1: hash后直接二分查询即可 #include<iostre ...

  6. 四连测Day1

    题目:链接: https://pan.baidu.com/s/163ycV64ioy7uML7AvRDTGw 密码: p86i T1: 倍增求LCA,minn数组记录最小值 #include<i ...

  7. (四连测)滑雪场的高度差题解---二分 + 搜索---DD(XYX)​​​​​​​的博客

    滑雪场的高度差 时间限制: 1 Sec  内存限制: 128 MB 题目描述 滑雪场可以看成M x N的网格状山地(1 <= M,N <= 500),每个网格是一个近似的平面,具有水平高度 ...

  8. STM32—TIMx实现编码器四倍频

    文章目录 一.储备知识 二.TIMx的编码器模式介绍 1.计数边沿设置 2.选择极性和使能 3.使能 4.计数方向 三.代码部分 一.储备知识 通过STM32的定时器编码器接口模式对编码器进行四倍频, ...

  9. Android支付接入(七):Google In-app-Billing

    前段时间有事请耽搁了,今天跟大家一起看下Google的in-app Billing V3支付.    如果没有Google Play此处附上安装Google Play的一键安装器的链接(需要Root权 ...

随机推荐

  1. WPF自定义依赖集合属性无法触发更新的问题

    通常WPF中通过继承UserControl的来快速创建自定义控件,最近项目上需要设计一个卫星星图显示控件,最终效果如下图所示.完成过程中遇到了自定义集合依赖属性无法触发更新通知的问题,在此记录一下,方 ...

  2. POJ 2456 Aggressive cows (二分 基础)

    Aggressive cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7924   Accepted: 3959 D ...

  3. jdk并发工具包之锁

    1.cynchronized扩展:可重锁入ReentrantLock ReentrantLock是通过cas算法实现的 RenntrantLock lock=new ReentrantLock(); ...

  4. Android 音频 OpenSL ES 录音 采集

    1,; int channelConfig = AudioFormat.CHANNEL_OUT_STEREO; int audioFormat = AudioFormat.ENCODING_PCM_1 ...

  5. android WebView详细使用方法(转)

    1.最全面的Android Webview详解 2.最全面总结 Android WebView与 JS 的交互方式 3.你不知道的 Android WebView 使用漏洞 如果想保证登录状态,就插入 ...

  6. Unity3D研究院编辑器之脚本设置ToolBar及脚本设置顶视图

    Unity版本5.3.2 如下图所示,ToolBar就是Unity顶部的那一横条.这里的所有按钮一般情况下都得我们手动的用鼠标去点击.这篇文章我们说说如果自动操作它们 1.自动点击左边四个按钮 (拖动 ...

  7. 开发及应用中 Linux与Window 取舍

    Linux是开源的,而Windows不是.这个也是Linux与Windows之间最大的差异.一般来说,开源似乎收到了更多系统管理员的亲睐,而开源的软件似乎更受个人电脑用户的欢迎.两种类型之间有很多不同 ...

  8. 【BZOJ4408】[Fjoi 2016]神秘数 主席树神题

    [BZOJ4408][Fjoi 2016]神秘数 Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13},1 = 12 = 1 ...

  9. Windows 下Nexus搭建Maven私服

    nexus下载地址: http://www.sonatype.org/nexus/archived/#step2top 1. 为什么使用Nexus 如果没有私服,我们所需的所有构件都需要通过maven ...

  10. 九度OJ 1014:排名 (排序)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8267 解决:2469 题目描述:     今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑每题的分 ...