Codeforces Round #441 Div. 2 E,F
来源:互联网 发布:linux服务器配置ipv6 编辑:程序博客网 时间:2024/05/22 06:56
E:
传送门
题意:
给
题解:
首先考虑怎么满足一个串比后面所有的都要小?是一个一个判断,还是有别的方法。
其实只要保证该串小等于后面的一个串就好了。
下面考虑怎么满足小等于后面的一个串。
设前面的串为
如果
同理若
不然设两串第一个不同的位置为
1.
2.
发现上面的思想就是
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>using namespace std;struct IO{ inline int read(){ char ch=getchar();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();} return i*f; } inline void W(int x){ static int buf[50]; if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10;x/=10;} while(buf[0])putchar(buf[buf[0]--]+'0'); }}io;const int Maxn=1e5+50;int n,m,dfn[Maxn<<1],low[Maxn<<1],st[Maxn<<1],top,tot,id[Maxn<<1],ind,ins[Maxn<<1];vector<int>ch[Maxn];vector<int>edge[Maxn<<1];#define is(x) 2*x-1#define isnot(x) 2*x#define addedge(x,y) edge[x].push_back(y)inline void dfs(int now){ dfn[now]=low[now]=++ind;st[++top]=now;ins[now]=1; for(int e=edge[now].size()-1;e>=0;e--){ int v=edge[now][e]; if(dfn[v]){ if(!ins[v])continue; low[now]=min(low[now],dfn[v]); } else dfs(v),low[now]=min(low[now],low[v]); } if(low[now]==dfn[now]){ ++tot; while(low[st[top]]==dfn[now]){ int u=st[top--]; id[u]=tot;ins[u]=0; } }}int main(){ n=io.read(),m=io.read(); for(int i=1;i<=n;i++){ int l=io.read(); for(int j=1;j<=l;j++){ ch[i].push_back(io.read()); } } for(int i=2;i<=n;i++){ int l1=ch[i-1].size(),l2=ch[i].size(),lim=min(l1,l2),pos=0; while(pos<lim&&ch[i-1][pos]==ch[i][pos])pos++; if(pos==lim){ if(l1>l2){ puts("No");return 0; } }else{ if(ch[i-1][pos]<ch[i][pos]){ addedge(is(ch[i-1][pos]),is(ch[i][pos])); addedge(isnot(ch[i][pos]),isnot(ch[i-1][pos])); }else{ addedge(isnot(ch[i][pos]),is(ch[i][pos])); addedge(is(ch[i-1][pos]),isnot(ch[i-1][pos])); } } } for(int i=1;i<=m;i++){ if(!dfn[is(i)])dfs(is(i)); if(!dfn[isnot(i)])dfs(isnot(i)); } static vector<int>ans; for(int i=1;i<=m;i++){ if(id[is(i)]>id[isnot(i)])ans.push_back(i); else if(id[is(i)]==id[isnot(i)]){ puts("No");return 0; } } puts("Yes"); printf("%d\n",(int)ans.size()); for(int e=0;e<ans.size();e++){ printf("%d ",ans[e]); }}
F:
传送门
题意:
求满足区间或大于区间最大值的区间个数。
题解:
考虑一个区间,只要这个区间的任意值非最大值有一位不与最大值相同,那么这个区间就是合法区间。
考虑找出所有值左右第一个大于它的位置,那么以它为最大值的区间就固定在这一段中。只要再找出这个区间中左右第一个有一位不与最大值相同的值的位置,那么这个位置左边的所有位置都可以与最大值右边的位置构成一个合法区间。右边也同理。
这样计算会有重复的部分,只需要减去两端算重的部分即可。
现在问题转化为找出每个值左右比他大的第一个位置,单调栈
同时,要求出左右第一个与最大值不同的位置,只需要
还有一种特殊的情况
其实只需要保证每个区间的最大值是最右边的那个值就行了。具体实现就是单调栈扫描一边满足
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>using namespace std;struct IO{ inline int read(){ char ch=getchar();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();} return i*f; } inline void W(int x){ static int buf[50]; if(!x){putchar('0');return;} if(x<0){putchar('-');x=-x;} while(x){buf[++buf[0]]=x%10;x/=10;} while(buf[0])putchar(buf[buf[0]--]+'0'); }}io;const int Maxn=2e5+50;int n,a[Maxn],l[Maxn],r[Maxn],st[Maxn],pos[Maxn],top,diff_l[Maxn],diff_r[Maxn],mx[35];int mxpos[35];int main(){ n=io.read(); for(int i=1;i<=n;i++)a[i]=io.read(); for(int i=1;i<=n;i++){ while(top&&st[top]<=a[i])top--; l[i]=pos[top]+1; st[++top]=a[i];pos[top]=i; } top=0;pos[top]=n+1; for(int i=n;i>=1;i--){ while(top&&st[top]<a[i])top--; r[i]=pos[top]-1; st[++top]=a[i];pos[top]=i; } for(int i=1;i<=n;i++){ int p=0; for(int j=0;(1ll<<j)<=a[i];j++){ if((1ll<<j)&a[i])mx[j]=max(mx[j],i); else p=max(p,mx[j]); } diff_l[i]=p; } fill(mx,mx+32+1,n+1); for(int i=n;i>=1;i--){ int p=n+1; for(int j=0;(1ll<<j)<=a[i];j++){ if((1ll<<j)&a[i])mx[j]=min(mx[j],i); else p=min(p,mx[j]); } diff_r[i]=p; } static long long ans=0; for(int i=1;i<=n;i++){ if(diff_l[i]>=l[i]){ ans+=1ll*(diff_l[i]-l[i]+1)*(r[i]-i+1); } if(diff_r[i]<=r[i]){ ans+=1ll*(r[i]-diff_r[i]+1)*(i-l[i]+1); } if(diff_l[i]>=l[i]&&diff_r[i]<=r[i]){ ans-=1ll*(r[i]-diff_r[i]+1)*(diff_l[i]-l[i]+1); } } cout<<ans<<endl;}
- Codeforces Round #441 Div. 2 E,F
- Codeforces Round #377 (Div. 2)(D.E.F)
- Codeforces Round #436 (Div. 2)E,F详解
- Codeforces Round #423 Div.2 A B C D E F
- Codeforces Round #424 Div.2 A B C D E F
- 解题报告:Codeforces Round #424 (Div. 2) A B C D E F
- Codeforces Round #435 (Div. 2)C,D,E,F题目详解
- Codeforces Round #277.5 (Div. 2) F
- Codeforces Round #279 (Div. 2) F
- Codeforces Round #279 (Div. 2) F
- Codeforces Round #279 (Div. 2) B F
- Codeforces Round #277.5 (Div. 2)F题
- Codeforces Round #322 (Div. 2) F
- Codeforces Round #377 (Div. 2) F
- Codeforces Round #386 (Div. 2) F
- Codeforces Round #442 (Div. 2) 877 F
- Codeforces Round #441 (Div. 2): E. National Property(模拟?)
- Codeforces Round #441 (Div. 2)-E-National Property(模拟)
- C语言关键字
- 刷题笔记:C/C++工程师能力评估2
- bzoj1452 [JSOI2009]Count
- Gym 101482. I
- 回文质数 构造回文数
- Codeforces Round #441 Div. 2 E,F
- Windows编程基础--第1节 第一个win32软件
- Course Schedule II
- Java之主函数——main函数
- sqoop1 脚本示例
- 普通用户sudo echo权限依旧写入不了文件
- java Executor线程池 中的Callable多线程讲解及实例
- java数据类型
- linux命令之远程访问