Codeforces Round #772 (Div. 2) CF1635ABCDEF
1635A - Min Or Sum
回忆性题意:改变两个数,但 或 不能变,求整个数组最小和。
挺好想的,只要抓住或运算有一位就够了,并且答案的构造非常可行,就可以解决了。
答案证明给出了一个式子a1∣a2∣...∣an≤a1+a2+...+ana_1|a_2|...|a_n\leq a_1+a_2+...+a_na1∣a2∣...∣an≤a1+a2+...+an挺对的。
1635B - Avoid Local Maximums
回忆性题意:通过最少次数调整,使得local maximum不复存在,比两边都大即是L.M.
我是直接上了就在想如果我是人会怎么做,简单发现,单有一个local maximum时,左右至少变一个;一个operation最多减少两个local max。然后结合样例不断改进自己的算法,就可以了。CF的样例是挺强的。
答案证明是把local max数全部先找出来,分组,每组必须要⌈每组个数2⌉\lceil \frac{每组个数}{2} \rceil⌈2每组个数⌉次操作。很对,这很数学。
1635C - Differential Sorting(构造)
回忆性题意:ax=ay-az,x<y<z,能否使a单调不减。
分类讨论,很好想的。贪心的去构造就完了。如果但是我留意到是not-decreasing,那构造一个除最后一个外,全部相同的就完事了。
比赛时,我想的是倒数第一个和倒数第二个是变不了的,倒数第三个只有一中改变方法,所以采取了从后往前推的方式,进一步想到了上面的方法。
很喜欢答案的证明,很数学,在an<0a_n<0an<0时,必有ai<0a_i<0ai<0通过反证法,结合ax=ay−aza_x=a_y-a_zax=ay−az可以推得矛盾ax>aya_x>a_yax>ay,妙。其实我也想到了,不过没有它这么数学化。
1635D - Infinite Set(DP)
乍一看我还以为是一个容斥问题,想放弃。没想到居然会是一个DP。
答案的思路很好,复杂问题,我们先从简单问题开始考虑:n=1,a1=1,p任意,能做吗?
最关键也是最巧妙的地方来了,我们把数分为几段,每一段为[2i−1,2i),i∈N∗[2^{i-1},2^{i}),i\in \N^*[2i−1,2i),i∈N∗。不妨定义f(x)f(x)f(x)表示的就是这个东西。那么我们能发现f(2x+1)=f(x)+1,f(4x)=f(x)+2f(2x+1)=f(x)+1,f(4x)=f(x)+2f(2x+1)=f(x)+1,f(4x)=f(x)+2。
这下,可以写出DP方程了:dp[i]=dp[i−1]+dp[i−2]dp[i]=dp[i-1]+dp[i-2]dp[i]=dp[i−1]+dp[i−2]。初始化dp[1]=1。答案为∑1pdp[i]\sum_{1}^{p}dp[i]∑1pdp[i]。
如果还原到原问题,那就是增加一个删去重复数的操作。排个序,小到大,奇数减1除2,偶数除4,最多logx\log xlogx的次数可以搞定一个数。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD=1e9+7;
const int N=2e5+10;int n,p;
int a[N];
ll f[N],g[N];
map<int,bool> b;bool check(int aa)
{while(aa>1){if(aa&1) aa=(aa-1)/2;else if(aa%4==0) aa=aa/4;else break;if(b[aa]) return false;}return true;
}int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> p;for(int i=1;i<=n;i++) cin >> a[i];sort(a+1,a+n+1);for(int i=1;i<=n;i++){if(a[i]==a[i-1]) continue;if(check(a[i])) b[a[i]]=true,g[__lg(a[i])+1]++;}ll ans=g[1];f[1]=g[1];for(int i=2;i<=p;i++) f[i]=(f[i-1]+f[i-2]+g[i])%MOD,ans=(ans+f[i])%MOD;
// for(int i=0;i<=p;i++) cout << f[i] << " " ;cout << ans << endl;return 0;
}
1635E - Cars(二分图染色)(拓补排序-巧) \ (差分约束)
题意:一种方案,让该相遇车的相遇,不的不。 可否?
挺有意思,想想能够到的题。先确定了不能同方向之后,发现很像二分图,因为只要出现了这两人的关系,他们就一定是反方向行驶,只是起点的左右问题决定是相遇还是不遇。进而,可以二分染色初步判定是否有界。(我年少无知以为新的就可以直接假定是L,殊不知,这个新可能只是没有更新到罢了。还得正正经经建个图、跑一下二分图染色。)
染完后,求一种起点的方案。看到不等式让我想到的是差分约束,建图判负环就OK,答案就是d[x]。差分约束记得要连一条(a0,ai,0)(a_0,a_i,0)(a0,ai,0)的边,即ai≤a0+0a_i\leq a_0+0ai≤a0+0,再假定a0=0a_0=0a0=0,对应到最短路就是d0=0d_0=0d0=0。
我还犯了一个错,ai<aja_i< a_jai<aj用差分约束的话来说应该是ai≤aj−1a_i \leq a_j -1ai≤aj−1。
不过这个O(nm)O(nm)O(nm)的时间复杂度最终TLE了。
答案说的好,不要大材小用差分约束,留意到每条边边权都是-1,可以直接用拓补排序。可以做到O(n)O(n)O(n)判负环,顺便还能把题给做了,何乐而不为呢。根据题目的特性来做题!!!
不加修饰的AC+TLE代码,将就将就把~
#include<bits/stdc++.h>
using namespace std;
const int INF=999999999;
const int N=2e5+10;int n,m,S;
int v[N];int du[N];struct node{int d,id;}d[N];
bool cmp1(node d1,node d2){return d1.d>d2.d;}
bool cmp2(node d1,node d2){return d1.id<d2.id;}struct E{int y,c,next;}e[2*N];int len=0,last[N];
void ins(int x,int y,int c)
{du[y]++;e[++len]=(E){y,c,last[x]};last[x]=len;
}bool check(int x)
{for(int k=last[x];k;k=e[k].next){int y=e[k].y;if(!v[y]){v[y]=3-v[x];if(!check(y)) return false;}if(v[y]+v[x]!=3) return false;}return true;
}struct Spfa
{queue<int> q;bool in[N];int cnt[N];bool SPFA(){for(int i=1;i<=n;i++) d[i]=(node){INF,i};d[S].d=0;q.push(S);while(!q.empty()){int x=q.front();q.pop();in[x]=false;for(int k=last[x];k;k=e[k].next){int y=e[k].y;if(d[y].d>d[x].d+e[k].c){d[y].d=d[x].d+e[k].c;cnt[y]++;if(cnt[y]>n) return false;//debug cnt[y]==n acutally has n+1 vetexif(!in[y]) q.push(y),in[y]=true;}}}return true;}
}sol1;struct TOPS
{queue<int> q;bool TopSort(){for(int i=1;i<=n;i++) d[i].id=i;int cnt=-1;q.push(S);while(!q.empty()){int x=q.front();q.pop();for(int k=last[x];k;k=e[k].next){int y=e[k].y;du[y]--;if(du[y]==0) d[y].d=d[x].d+1,q.push(y);}cnt++;}return cnt==n;}
}sol2;int opt[N],a[N],b[N];
int main()
{ios::sync_with_stdio(false);cin.tie(0);cin>>n>>m;for(int i=1;i<=m;i++){cin>>opt[i]>>a[i]>>b[i];ins(a[i],b[i],0);ins(b[i],a[i],0);}for(int i=1;i<=n;i++) if(!v[i]){v[i]=1;if(!check(i)) goto fail;}S=n+1;len=0;memset(last,0,sizeof(last));memset(du,0,sizeof(du));for(int i=1;i<=m;i++){int x=a[i],y=b[i];if(opt[i]==1) ins( v[x]>v[y]?x:y , v[x]<v[y]?x:y , -1);//dy(v[x]=1)<=dx(v[x]=2)-1 else ins( v[x]<v[y]?x:y , v[x]>v[y]?x:y , -1);//dy(v[x]=2)<=dx(v[x]=1)-1 }for(int i=1;i<=n;i++) ins(S,i,0);
// if(!sol1.SPFA()) goto fail;if(!sol2.TopSort()) goto fail;sort(d+1,d+n+1,cmp1);for(int i=1;i<=n;i++) d[i].d=i;sort(d+1,d+n+1,cmp2);cout<<"YES"<<endl;for(int i=1;i<=n;i++) cout<< (v[i]==1?"L ":"R ") << d[i].d <<endl;return 0;fail:cout<<"NO"<<endl;return 0;
}
1635F - Closest Pair(性质分析)(栈)(树状数组)
题意:区间内取两数,使得∣xi−xj∣∗(wi+wj)|x_i-x_j|*(w_i+w_j)∣xi−xj∣∗(wi+wj)最小。
我以后也要用cin,cout了,很不错的样子,主要是打起来比scanf方便很多,少了很多引号和地址符的烦恼。第一次这么大规模用vector,可惜DEV-C++不争气,版本太落后了,很多高级语句都只能替换掉了。找个时间配一个新的编译器!
是我太弱了,看了好几天终于看懂了F题的tutorial。下面还原一下tutorial的精彩证明:
Lemma:定义L[i]L[i]L[i]为最大的jjj,满足x[j]<x[i]x[j]<x[i]x[j]<x[i],并且w[j]≤w[i]w[j]\leq w[i]w[j]≤w[i];R[i]R[i]R[i]为最小的jjj满足x[i]<x[j]x[i]<x[j]x[i]<x[j],并且w[j]≤w[i]w[j]\leq w[i]w[j]≤w[i]。那么,所有求得的区间一定在(L[i],i)(L[i],i)(L[i],i),和(R[i],i)(R[i],i)(R[i],i)之间。
Proof:对于一对数(a,b)是区间内最优方案,
- 如果w[a]<=w[b], 那么一定会有L[b]=a(成立了吧);否则(如果L[b]敢不等于a),那么(a,L[b])将会是比(a,b),更优的选择方案(矛盾了,所以L[b]是不敢不等于a的)。
- 如果w[a]>w[b],那么一定会有R[a]=b(成立了吧);否则,(R[a],b)是更优的方案。
证明的后半段是反证法,来说明前面是一定成立的。
一个字:绝!
这个定理中的L[i]L[i]L[i]和R[i]R[i]R[i]是很好用一个栈去把它求出来的。有了这个定理后,我们需要处理的内容就大大减少了。
tutorial给出了一种题意转换,把选择的两个点连一条边,并附上权值。现在题目变成了,给出2n2n2n条带权线段,问位于区间[l,r][l,r][l,r]内线段的最大权值。用扫描线+统计后缀和的一个工具(如BIT树)就可以了。
时间复杂度O((n+q)logn)O((n+q)\log n)O((n+q)logn)
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 300005;
const ll INF=1ll<<62;int n,q;
vector<pii> queries[N];
vector<int> useful[N];ll bit[N];
void modify(int x,ll val)
{for(;x;x-=x&-x) bit[x]=min(bit[x],val);
}
ll query(int x) //debug int query()
{ll re=INF;for(;x<=n;x+=x&-x) re=min(re,bit[x]);return re;
}int main()
{ios::sync_with_stdio(false);cin.tie(0);cin>>n>>q;vector<int> x(n+1),w(n+1);for(int i=1;i<=n;i++) cin>>x[i]>>w[i];for(int i=1;i<=q;i++){int l,r;cin>>l>>r;queries[r].push_back(mp(l,i));}stack<int> stk;for(int i=1;i<=n;i++){while(!stk.empty() && w[stk.top()]>w[i]) stk.pop();if(!stk.empty()) useful[i].push_back(stk.top());stk.push(i);}while(!stk.empty()) stk.pop();for(int i=n;i>=1;i--){while(!stk.empty() && w[stk.top()]>w[i]) stk.pop();if(!stk.empty()) useful[stk.top()].push_back(i);stk.push(i);}vector<ll> ans(q+1);//debug vector<int> ans(n+1);memset(bit,0x3f,sizeof bit);for(int r=1;r<=n;r++){for(vector<int>::iterator it=useful[r].begin();it<useful[r].end();it++){int l=*it;ll val=1ll*(x[r]-x[l])*(w[l]+w[r]);modify(l,val);}for(vector<pii>::iterator it=queries[r].begin();it<queries[r].end();it++){int l=it->first,id=it->second;ans[id]=query(l);}}for(int i=1;i<=q;i++) cout << ans[i] << endl; //debug i<=nreturn 0;}
Codeforces Round #772 (Div. 2) CF1635ABCDEF相关推荐
- Codeforces Round #772 (Div. 2) D. Infinite Set (动态规划+思维)
题目链接 https://codeforces.com/contest/1635/problem/D 题面 题意 输入一个n表示数组 aaa 的长度,然后输入一个 p,然后输入n个不同的元素,问在 [ ...
- Codeforces Round #772 (Div. 2) C. Differential Sorting(思维+构造)
题目链接 https://codeforces.com/contest/1635/problem/C 题面 题意 给你一个长度为n的数组 a[i]a[i]a[i] ,我们有一种操作让 a[x]=a[y ...
- Codeforces Round #506 (Div. 3)
Codeforces Round #506 (Div. 3) 实习期间事不多,对div3 面向题解和数据编程了一波 A. Many Equal Substrings 题目链接 A题就是找后缀和前缀重合 ...
- Codeforces Round #563 (Div. 2)/CF1174
Codeforces Round #563 (Div. 2)/CF1174 CF1174A Ehab Fails to Be Thanos 其实就是要\(\sum\limits_{i=1}^n a_i ...
- 构造 Codeforces Round #302 (Div. 2) B Sea and Islands
题目传送门 1 /* 2 题意:在n^n的海洋里是否有k块陆地 3 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 4 输出完k个L后,之后全部输出S:) 5 5 10 的例子可以 ...
- Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解(每日训练 Day.16 )
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解 比赛链接:h ...
- Codeforces Round #712 Div.2(A ~ F) 超高质量题解(每日训练 Day.15 )
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #712 Div.2(A ~ F) 题解 比赛链接:https:// ...
- Codeforces Round #701 (Div. 2) A ~ F ,6题全,超高质量良心题解【每日亿题】2021/2/13
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A - Add and Divide B - Replace and Keep Sorted C ...
- Codeforces Round #700 (Div. 2) D2 Painting the Array II(最通俗易懂的贪心策略讲解)看不懂来打我 ~
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 整场比赛的A ~ E 6题全,全部题目超高质量题解链接: Codeforces Round #700 ...
最新文章
- TensorRT是NVIDIA开发的深度学习推理工具,只支持推理,不支持训练 引
- CryEngine最新版发布,支持Vulkan API
- SpringMVC之源码分析--HandlerMapping(一)
- nema gps数据转换 matlab,GPS通信的NEMA协议与定位数据的提取.pdf
- linux内核参数备注
- mysql内存片多大_内存带宽对mysql影响多大?
- GPU是如何工作的?
- 安卓通过js与网页的H5页面进行交换
- python音乐下载器
- 【竞赛篇-申报平台】浙江省国创(大创)平台里导出的word显示不出图片、右边界溢出页面,图片空间不足的解决办法
- 计算机设备全年销售表,2021年计算机机房设备行业财务部门表格模板汇总 .pdf
- 鸿蒙系统桌面建文件夹,怎样把桌面上的文件放在一个文件夹里
- 新一配:perl循环调用python爬虫批量下载喜马拉雅音频
- MCU设计之 - 启动模式(Boot0Boot1)
- 我的世界基岩版好还是java版好_【Minecraft/我的世界】Java版和基岩版的区别(1)...
- python如何调用谷歌搜图api_python爬虫——selenium+chrome使用代理
- 小程序用户头像昵称获取不到解决办法
- Linux时间 新纪元 epoch time
- Linux进程监视器——htop详解
- Android-Studio与Python环境配置