Codforces1181B 大数加法 Cdeque D树状数组

长为n数字 2-1e5
分成两部分不能有先导0 求和最小

 #include <iostream>
 #include <string>
 #include <vector>
 using namespace std;
 int n;//接收数字位数
 string s;//接收数字
 vector<int> vec;//来存值不为零的元素的索引
 string rm0(string a)//删除前导零
 {
     int i;
     for(i = 0;i<a.size();i++)
     {
         if(a[i]!='0')
         {
             break;
         }
     }
     a = a.substr(i);
     return a;
 }
 string add(string a,string b)//大数加法
 {
     if(a.size()<b.size()) //先把两者位数补成一样的
     {
         swap(a,b);
     }
     a = '0'+a;
     while(b.size()<a.size())
     {
         b = '0'+b;
     }
     int c = 0;
     for(int i = b.size()-1;i>=0;i--) //从低位到高位加
     {
         int sum = c+(int)a[i]-'0'+(int)b[i]-'0';
         if(sum>=10)
         {
             a[i] = (char)sum-10+'0';
             c = 1;
         }
         else
         {
             a[i] = (char)sum+'0';
             c = 0;
         }
     }
     a = rm0(a);
     return a;
 }
 int larger(string a,string b)//判断a是不是大于等于b
 {
     if(a.size()!=b.size())
     {
         return a.size()>b.size();
     }
     else
     {
         for(int i = 0;i<a.size();i++)
         {
             if(a[i]!=b[i])
             {
                 return a[i]>b[i];
             }
         }
     }
     return 1;
 }
 int main()
 {
     cin >> n >> s;
     string a = "";
     string b = "";
     for(int i = 0;i<n;i++)
     {
         if(s[i]!='0')
         {
             vec.push_back(i);
         }
     }
     int mid = lower_bound(vec.begin(),vec.end(),n/2)-vec.begin();//找不为零的接近中间位置的数在原数组的索引
     string ans = s;
     for(int i = -2;i<3;i++)//在索引附近遍历一遍
     {
         int pos = max(1,min((int)vec.size()-1,mid+i));
         a = s.substr(0,vec[pos]);
         b = s.substr(vec[pos]);
         string res = add(a,b);
         if(larger(ans,res))
         {
             ans = res;//取最小值
         }
     }
     cout << ans << endl;
     return 0;
 }

C数据结构 双端队列

#include<bits/stdc++.h>
using namespace std;
typedef pair<char,int> P;
const int maxn=1003,INF=1050000000;
char s[maxn];
int n,m;
long long ans;
deque<P> a[maxn];
bool valid(const deque<P> &q){
    return q.size()==3&&q[0].second>=q[1].second&&q[1].second==q[2].second;
}
bool equal(const deque<P> &q1,const deque<P> &q2){
    if(q2.size()!=3)return 0;
    for(int i=0;i<=2;i++)if(q1[i].first!=q2[i].first)return 0;
    return q1[1].second==q2[1].second&&q1[2].second==q2[2].second;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=m;j++){
            if(a[j].size()>=1&&a[j].back().first==s[j])a[j].back().second++;
            else a[j].push_back(P(s[j],1));
            while(a[j].size()>=2&&a[j].back().second>a[j][a[j].size()-2].second)a[j].pop_front();
            if(a[j].size()>=4)a[j].pop_front();
        }
        for(int l=1,r=1;r<=m;l=r){
            for(;l<=m&&!valid(a[l]);l++);
            for(r=l;r<=m&&valid(a[r])&&equal(a[l],a[r]);r++);
            ans+=(long long)(r-l)*(r-l+1)/2;
        }
    }
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值