选出三个序列使之不能组成三角形。先把差距最大的选了,枚举中间值。两边之和不大于第三边。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
using namespace std;
const int N=50010;
int a[N];
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int i;
for(i=2;i<n;i++)
if(a[1]+a[i]<=a[n])
break;
if(i==n) cout<<-1<<endl;
else cout<<1<<' '<<i<<' '<<n<<endl;
}
return 0;
}
第一次没加#include
还Compilation error
了。。
考虑原串中连续的1。两人一定轮流选择目前连续1个数最多的。把连续的1个数存到一个数组,逆序。两人轮流取即可。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
#include
#include
using namespace std;
const int N=110;
int a[N];
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
string s;
cin>>s;
int n=s.size();
vector<int> ans(n);
for(int i=1;i<=n;i++) a[i]=s[i-1]-'0';
for(int i=1;i<=n;i++)
{
int j=i;
while(j<=n&&a[i]==a[j]) j++;
if(a[i]==1) ans.push_back(j-i);
i=j-1;
}
int res=0;
sort(ans.begin(),ans.end());
reverse(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++)
if(i%2==0) res+=ans[i];
cout<<res<<endl;
}
return 0;
}
对于原数组 a [ l + 1 ] + a [ l + 2 ] + ⋯ + a [ r ] = r − l + 1 a[l+1]+a[l+2]+\dots+a[r]=r-l+1 a[l+1]+a[l+2]+⋯+a[r]=r−l+1考虑前缀和数组即 a [ r ] − a [ l ] = r − l a[r]-a[l]=r-l a[r]−a[l]=r−l变换一下 a [ r ] − r = a [ l ] − l a[r]-r=a[l]-l a[r]−r=a[l]−l。因此只需统计 a [ i ] − i a[i]-i a[i]−i的个数,根据组合数的计算公式即可。由于可能有负数弄了个map
映射。上述情况未考虑i=0
的情况,因此最后应加上a[i]==i
的个数。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=100010;
int a[N];
map<int,int> mp;
int idx=0;
int get(int s)
{
if(!mp.count(s)) mp[s]=++idx;
return mp[s];
}
ll cnt[N];
int main()
{
IO;
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
mp.clear();
for(int i=0;i<=n;i++) cnt[i]=0;
idx=0;
string s;
cin>>s;
for(int i=1;i<=n;i++) a[i]=s[i-1]-'0';
for(int i=1;i<=n;i++) a[i]+=a[i-1];
for(int i=1;i<=n;i++) cnt[get(a[i]-i)]++;
ll res=0;
for(int i=1;i<=idx;i++) res+=1ll*cnt[i]*(cnt[i]-1)/2;
for(int i=1;i<=n;i++)
if(a[i]==i) res++;
cout<<res<<endl;
}
return 0;
}
这题很快就想到怎么写了,但是码代码能力还是不行写了半天。最开始没想用map
弄明白数组开多大烦死了(负数可以平移)然后就用map
了。看群里讨论发现负数不一定平移,可以为负数多开一个数组记录a[-i],i<0
。
首先贪心,对于每一对木条,肯定选择长的。因此先降序排列数组。
f[i][j][k]
表示:R用了i个,G用了j个,B用了k个的集合。转移考虑最后用的是那一对木棒。
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=210;
int a[N],b[N],c[N];
int f[N][N][N];
int cnta,cntb,cntc;
int main()
{
IO;
cin>>cnta>>cntb>>cntc;
for(int i=1;i<=cnta;i++) cin>>a[i];
for(int i=1;i<=cntb;i++) cin>>b[i];
for(int i=1;i<=cntc;i++) cin>>c[i];
sort(a+1,a+1+cnta);
sort(b+1,b+1+cntb);
sort(c+1,c+1+cntc);
reverse(a+1,a+1+cnta);
reverse(b+1,b+1+cntb);
reverse(c+1,c+1+cntc);
for(int i=0;i<=cnta;i++)
for(int j=0;j<=cntb;j++)
for(int k=0;k<=cntc;k++)
{
if(i&&j&&(i+j+k)%2==0) f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k]+a[i]*b[j]);
if(j&&k&&(i+j+k)%2==0) f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+c[k]*b[j]);
if(i&&k&&(i+j+k)%2==0) f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+a[i]*c[k]);
}
int res=0;
for(int i=0;i<=cnta;i++) res=max(res,f[i][cntb][cntc]);
for(int i=0;i<=cntb;i++) res=max(res,f[cnta][i][cntc]);
for(int i=0;i<=cntc;i++) res=max(res,f[cnta][cntb][i]);
cout<<res<<endl;
return 0;
}
D题最后1分钟提交的太惊险了。
群里大佬说是权值线段树+离散化,这个我学过补一下吧。
如果有k
个lightning
,那么能过翻倍k-1
或者k
个伤害(讨论一下),翻倍肯定翻倍最大的几个,因此考虑权值线段树(因此需要离散化)维护前k
大,一般有删除加入需要用set
维护,数据无重复,让题目简单不少。
lower_bound
只能够在升序情况下使用
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=200010;
int n;
pii q[N];
vector<int> id;
struct node
{
int l,r,cnt;
ll sum;
}tree[N*4];
int get(int a)
{
int l=0,r=id.size()-1;
while(l<r)
{
int mid=l+r>>1;
if(id[mid]<=a) r=mid;
else l=mid+1;
}
return l+1;
}
void pushup(int u)
{
tree[u].cnt=tree[u<<1].cnt+tree[u<<1|1].cnt;
tree[u].sum=tree[u<<1].sum+tree[u<<1|1].sum;
}
void build(int u,int l,int r)
{
tree[u]={l,r,0,0};
if(l==r) return;
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
}
void modify(int u,int k,int x)
{
if(tree[u].l==tree[u].r)
{
tree[u].cnt+=x;
tree[u].sum+=x*id[k-1];
return;
}
int mid=tree[u].l+tree[u].r>>1;
if(k<=mid) modify(u<<1,k,x);
else modify(u<<1|1,k,x);
pushup(u);
}
ll query(int u,int k)
{
if(tree[u].l==tree[u].r) return tree[u].sum;
int tmp=tree[u<<1].cnt;
if(tmp>=k) return query(u<<1,k);
else return tree[u<<1].sum+query(u<<1|1,k-tmp);
}
int main()
{
IO;
cin>>n;
build(1,1,n);
for(int i=1;i<=n;i++)
{
cin>>q[i].first>>q[i].second;
id.push_back(abs(q[i].second));
}
sort(id.begin(),id.end());
id.erase(unique(id.begin(),id.end()),id.end());
reverse(id.begin(),id.end());
set<int> fire,lightning;
int k=0;
ll res=0;
for(int i=1;i<=n;i++)
{
if(q[i].first==1)
{
if(q[i].second>0)
{
k++;
lightning.insert(q[i].second);
res+=q[i].second;
modify(1,get(q[i].second),1);
}
else
{
k--;
lightning.erase(-q[i].second);
res+=q[i].second;
modify(1,get(-q[i].second),-1);
}
}
else
{
if(q[i].second>0)
{
fire.insert(q[i].second);
res+=q[i].second;
modify(1,get(q[i].second),1);
}
else
{
fire.erase(-q[i].second);
res+=q[i].second;
modify(1,get(-q[i].second),-1);
}
}
if(fire.empty())
{
if(k>1)
cout<<res+query(1,k-1)<<'\n';
else cout<<res<<'\n';
}
else if(lightning.empty()) cout<<res<<'\n';
else
{
int minl=*lightning.begin();
auto t=fire.end();
t--;
int maxf=*t;
if(minl>maxf)
{
if(k>1) cout<<res+query(1,k-1)+maxf<<'\n';
else cout<<res+maxf<<'\n';
}
else
{
if(k>0) cout<<res+query(1,k)<<'\n';
else cout<<res<<'\n';
}
}
}
return 0;
}
要加油哦~