当前位置: 首页 > news >正文

23ICPC济南站补题

济南…我想家了…
不拿牌没脸回家
原题链接
思路来源

D 思维

void solve() {int la,ra,lb,rb;cin>>la>>ra>>lb>>rb;int l=la+lb,r=ra+rb;if(r-l>=10)return cout<<9<<endl,void();//会经过有9的数//以下r-l<10int le=l%10,re=r%10;string ls=to_string(l),rs=to_string(r);int ans=0;if(re>=le){//前面的数都一样ans=re;for(auto c:rs)ans=max(ans,(int)(c-'0'));}else{ans=9;//会经过有9的数}cout<<ans<<endl;
}

A 找规律

多列几组样例找规律
不合法的情况:

  • 连续同类括号的多于2个 如()()() ()([()])()
  • 总的成对的
    • 没有
    • 多于三个 如()[()][()] (),两边的也可以组合
int jud(char c){int res=-1;if(c=='('||c==')')res=0;if(c=='['||c==']')res=1;return res;
}
void solve() {string s;cin>>s;//总的成对的 连续的int cnt=0,con=0;forr(i,1,s.size()-1){if(jud(s[i])==jud(s[i-1])){cnt++;con++;if(con>=2)return cout<<"No"<<endl,void();}else con=0;}if(cnt==2||cnt==1)cout<<"Yes"<<endl;else cout<<"No"<<endl;
}

I 模拟 思维

只要找到尽量远的l,rl,rl,ral>ara_l>a_ral>ar就换
注意排列后不一定归位,不能直接跳过排序的区间
如1 2 3 4 5 6 8 10 7 9->1 2 3 4 5 6 7 8 10 9

void solve() {int n;cin>>n;vector<int>a(n+1);int fg=0;forr(i,1,n){cin>>a[i];if(a[i]!=i)fg=1;}if(!fg)return cout<<0<<endl,void();vector<pii>ans;int st=1;forr(i,1,n)if(a[i]!=i){st=i;break;}for(int i=st;i<=n;i++){if(a[i]==i)continue;// int ed=n;for(int j=n;j>i;j--){if(a[i]>a[j]){// ed=j;ans.push_back({i,j});sort(a.begin()+i,a.begin()+j+1);//把大的放到后面 跟后面比较break;}}//不能直接跳过 前面被排序的中间也会有一些没归位的数// i=ed-1;//注意下一步i++}cout<<ans.size()<<endl;for(auto i:ans)cout<<i.first<<' '<<i.second<<endl;
}

G 并查集 图论

每行可翻转,每列维持1的数目<=1,有多少种行反转的组合
发现

  • 有的行两两之间有一个固定的关系,有×2\times2×2的贡献,但是可能也有互相制约
  • 有的行左右反转都可以,也有×2\times2×2的贡献

把关系转化成图
用并查集表示固定关系,相互连通的互斥,一个连通块就是一个关系,每个关系有×2\times2×2的贡献

1:如果第 i 列和第 n - i + 1 列的 1 的数量之和小于等于 1 那么这 个 1 所在的一行翻转和不翻转都可以
2:如果第 i 列和第 n - i + 1 列的 1 的数量之和为2
  (1):如果这两个 1 在同一列,那么这两行(指的是这两个1所在的行)必须翻转一个
  (2):如果这两个 1 不在同一列,那么这两行(同上)必须要不都翻转,要不都不翻转

const int N=1e6+5,C=1e6+10,mod=1e9+7,inf=1e9+10;
string s[N];
int r,c;
int fa[N*2];
void init(){forr(i,1,2*r)fa[i]=i;
}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y){int fx=find(x),fy=find(y);fa[fx]=fy;
}int tpow(int a,int b){int res=1;for(;b;b>>=1,(a*=a)%=mod)if(b&1)(res*=a)%=mod;return res;
}
void solve() {cin>>r>>c;init();forr(i,1,r){cin>>s[i];s[i]=' '+s[i];}forr(i,1,(c+1)/2){//奇数列要处理中间的,因为中心翻转后不变int cnt=0;forr(j,1,r){cnt+=(s[j][i]=='1')+(s[j][c-i+1]=='1');}if(cnt>2)return cout<<0<<endl,void();//对称两列上的1个数>2 怎么转每列也不能达到<=1}forr(j,1,(c+1)/2){vector<int>lp,rp;forr(i,1,r){if(s[i][j]=='1')lp.push_back(i);if(s[i][c-j+1]=='1')rp.push_back(i);}// cout<<lp.size()<<' '<<rp.size()<<endl;//i+r表示反转状态//在同一列:一行反转一行不变if(lp.size()==2){merge(lp[0],lp[1]+r);merge(lp[0]+r,lp[1]);}else if(rp.size()==2){merge(rp[0],rp[1]+r);merge(rp[0]+r,rp[1]);}//两列1的个数<2 翻不翻都可else if(lp.size()==0||rp.size()==0)continue;//不在同列:一起变else{merge(lp[0],rp[0]);merge(lp[0]+r,rp[0]+r);}}// forr(i,1,2*r)cout<<i<<' '<<fa[i]<<endl;forr(i,1,r){//第i行不变和反转在同一关系中 相互矛盾if(find(i)==find(i+r))return cout<<0<<endl,void();}int ans=0;forr(i,1,2*r)ans+=fa[i]==i;// cout<<ans<<endl;cout<<tpow(2,ans/2)<<endl;
}

K 滑动窗口 求中位数

思路来源
一开始想用二分去做,但是苦于check怎么求出长度内的修改次数。
ai+1−ai=1a_{i+1}-a_i=1ai+1ai=1可以变成ai−i=aj−ja_i-i=a_j-jaii=ajj,每个数都减去下标后都改成相同的数会产生彩虹数组。
最小的操作次数就是改成长度内的中位数,使用双set维护中位数,有O(logn)O(logn)O(logn)的复杂度。
使用二分,check中定长窗口,set维护,总复杂度O(nlog2n)O(nlog^2n)O(nlog2n)会超时。
所以直接使用滑动数组,O(nlogn)O(nlogn)O(nlogn)找长度。

int n,k;
// set找中位数
multiset<int>gs,ls;//ls<mid<gs
int gsm,lsm;
// 平衡中位数两边
void blc(){while (ls.size()+1<gs.size()&&gs.size()){auto tp=gs.begin();gsm-=*tp,lsm+=*tp;ls.insert(*tp);gs.erase(tp);}while (ls.size()>gs.size()&&ls.size()){auto tp=ls.end();tp--;gsm+=*tp,lsm-=*tp;gs.insert(*tp);ls.erase(tp);}
}
void solve() {cin>>n>>k;vector<int>a(n+1);forr(i,1,n)cin>>a[i];if(n==1)return cout<<1<<endl,void();forr(i,1,n)a[i]=a[i]-i;//神奇性质:a[i+1]-a[i]=1=i+1-i   a[i+1]-(i+1)=a[i]-i//滑动窗口gsm=lsm=0;gs.clear();ls.clear();int ans=1,mid=a[1],bg=1,sm=0;gs.insert(a[1]),gsm+=a[1];forr(i,2,n){if(a[i]>=mid)gs.insert(a[i]),gsm+=a[i];//滑进窗口else ls.insert(a[i]),lsm+=a[i];blc();mid=*gs.begin();sm=(ls.size()*mid-lsm)+(gsm-gs.size()*mid);while(sm>k){if(a[bg]>=mid)gs.erase(gs.find(a[bg])),gsm-=a[bg];else ls.erase(ls.find(a[bg])),lsm-=a[bg];blc();//增减数组后进行平衡 否则会内存错误remid=*gs.begin();sm=(ls.size()*mid-lsm)+(gsm-gs.size()*mid);bg++;//前面的滑出窗口}ans=max(ans,i-bg+1);}// cout<<"ans";cout<<ans<<endl;
}
http://www.dtcms.com/a/439245.html

相关文章:

  • 商务网站建设ppt模板培训网站排名
  • 南阳市宛城区建设局网站设计本质
  • nacos使用指南
  • 中山AI搜索哪家好?GEO优化与传统SEO深度解析
  • MySQL优化----非查询SQL优化
  • 影视网站代理徐州市经济技术开发区建设局网站
  • 基于单片机的三相逆变电源设计
  • Python基础入门例程92-NP92 公式计算器
  • MyCat实现分库分表
  • 宿迁网站建设公司宣传海报制作
  • 中铁中基建设集团网站品牌形象网站源码
  • 中医院网站源码传智黑马培训机构
  • python全栈(基础篇)——day01:环境准备(python解释器安装+pycharm专业版的下载+vscode编辑器+汉化设置)
  • CodeForces Round 1054(div.3)C题
  • 南宁网站建设制作定制seo搜索引擎优化招聘
  • 3.java常用类知识点
  • 费马小定理证明
  • 建设中网站源码微信小程序怎么注册申请
  • iis7.5 没有默认网站彩票网站代理
  • 汇编语言Debug工具与常用指令完全指南
  • wordpress 托管建站有了公网ip如何做网站
  • 网站的费用多少合肥网站开发建设
  • 零基础学习做网站蚌埠做网站建设费用
  • 麒麟系统安装后添加自启动
  • 网站底部备案号悬挂佛山木工机械厂骏域网站建设专家
  • 顺序表专题
  • 网站 备案 中国 名字微网站模板代码
  • ASP.NET Core Web API 中控制器操作的返回类型及Swagger
  • AI模型测评平台工程化实战十二讲(第六讲:大模型测评系统:智能模型管理模块的设计与实现)
  • 手写MyBatis第90弹:动态SQL测试策略与验证方法