热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

牛客算法入门竞赛笔记1

2021-10-20:昨天开的新坑,看了前几集感觉还可以,后悔为什么没早点跟着学,以前就感觉到了自己的知识体系太散了,这个课好像是11月还是12月结束,她说能达到icpc铜牌水平,

2021-10-20:昨天开的新坑,看了前几集感觉还可以,后悔为什么没早点跟着学,以前就感觉到了自己的知识体系太散了,这个课好像是11月还是12月结束,她说能达到icpc铜牌水平,我姑且相信好吧,希望跟着学完能有点进步,不求铜牌,cf先能上个1500吧呜呜呜。

# 模拟,枚举与贪心

字符串 (nowcoder.com)

 

尺取法(说实话这可能是我第一次见到这个做法,或者第一次知道它的学名),正常暴力想法应该是枚举两个端点,但是这里的右端点其实不用后退,想一下就知道了,因此只要两个端点差速右移就是O(n)的复杂度了

 #include
 using namespace std;
 int main(){
  mapx;
  string a;
  cin>>a;
  int l=0,r=0;
  for(int i=0;i1){
  x[a[i]]--;
  i++;
  }
  if(x.size()==26){
  ans=min(ans,r-i+1);
  }
  if(r==a.size()-1){
  break;
  }
  }
  cout<  return 0;
 }

丢手绢 (nowcoder.com)

尺取+1,但是我第一发wa了,90分,因为每一次移动要考虑的不仅是逆时针的最大值,还有顺时针的最大值。

 #include
 using namespace std;
 #define ll long long
 ll x[100001];
 int main(){
  int n;
  cin>>n;
  ll sum=0;
  for(int i=0;i  cin>>x[i];
  sum+=x[i];
  }
  ll l=0,r=0;
  ll now=0,ans=0;
  while(1){
  while(now*2<=sum&&r<=n-1){
  ans=max(now,ans);
  now+=x[r];
  r++;
  }
  while(now*2>sum){
  ans=max(ans,sum-now);//第一发没加这一句
  now-=x[l];
  l++;
  }
  if(r==n){
  break;
  }
  }
  cout<

Flip Game (nowcoder.com)

黑白棋问题:

1-每个棋子最多只能翻一次

2-我们枚举第一行的翻法(16种),然后递推出第二第三行的翻法(上一行哪个没翻第二行就翻下面那个),如果第四行都翻过来了,就成功,否则失败

题解里有个位运算的做法贼牛逼,把每一行都看成二进制串,假设我按第一个和第三个,那么对应的按操作的二进制码就是1010,现在我一共要对三个地方取反,第一:本位取反,直接让原码和操作码异或,第二:每个按操作的左边取反,操作码左移一位再异或,第三:每个按操作的右边取反,操作码右移一位再异或。

异或就是不进位的二进制加(好记)

看课程里老师调了半天,而我一眼就看出她那里有问题,给我急得()

 #include
 #include
 #define INF 0x3f3f3f3f
 using namespace std;
 ​
 int a[5],b[5];
 int ans=INF;
 ​
 int count_1_num(int x){
  int num=0;
  while(x>=1){
  num+=x%2;
  x/=2;
  }
  return num;
 }
 ​
 int fun(int*x){
  int t[5];
     //枚举16种第一行的情况
  for(int i=0;i<16;i++){
         //计算有几个1,就代表翻转了几次
  int num=count_1_num(i);
  for(int i=0;i<4;i++){
  t[i]=x[i];
  }
  t[0]=(t[0]^(i)^(i<<1)^(i>>1));
  t[1]=(t[1]^(i));
  t[0]=(t[0]&15);
  for(int k=1;k<4;k++){
  num+=count_1_num(t[k-1]);
  t[k]=(t[k]^(t[k-1])^(t[k-1]<<1)^(t[k-1]>>1));
  t[k+1]=(t[k+1]^(t[k-1]));
  //把有可能溢出的第五位变成0(这步是我没想到的)
  t[k]=t[k]&15;
  }
  if(t[3]==0){
  ans=min(num,ans);
  }
  }
 }
 ​
 int main(){
  for(int i=0;i<4;i++){
  for(int k=0;k<4;k++){
  char c;
  scanf(" %c",&c);
  if(c=='b'){
  //把a[i]的第k+1位变成1
  a[i]=a[i] | (1<  }else{
  b[i]=b[i] | (1<  }
  }
  }
  fun(a);
  fun(b);
     //第一发忘了加impossible居然0分是我没想到的,难道说。。。
  if(ans==INF){
  cout<<"Impossible"<  return 0;
  }
  cout<



 

 

震惊我一整年的做法,原题数据范围很小,可以把所有学号相加减去来的,但是如果数据范围非常大,学号之和已经超过long long了,就不能这样做了

于是,它来了,位运算:加减相消的原理和两次异或不变的原理是互通的,所以我们可以把所有的学号异或起来,然后再异或掉来的人的学号,剩下的就是没来的。

艹,太帅了,我直接拜发明这个算法的人为师,orz

再升级一下,如果两个人没来呢?

先和上面一样操作一遍得到两个没来的人的学号异或值,找到一位为1的,表明这两个人在这一位上不同,就可以将原数分为两块,每一块都是一个人没来的问题。

ohhhhhh,130没白花,长见识了。

Problem - 333E - Codeforces

 

这题听他讲好像没什么,一搜2500,妈耶,我到底在学什么,我一个1300分的人也配想2500的题?

思路很巧妙,我们枚举两两点之间的距离,将其从大到小排序,从长边到短边,构成的第一个三角形的最短边长的一半就是答案

但是。我们怎么判断什么时候构成一个三角形呢,最质朴的想法就是我每走过一条边都记录下每个点对应的已经检验过的邻点,如果出现一条边AC,A已经走过B,C也已经走过B,就成了,但是如果正常记录遍历的话必定会超时,怎么办呢? 震惊我两整年的想法来了,c++里有一个bitset类,就是一个很长的二进制串,我们存走过的点时,给它转化成对应的bitset位的值,然后每条新边来的时候判断一下两个端点的bitset的位与,如果不为零,就说明他们之前经过过同一个点,齐活!

我居然自己写出来了,艹,牛逼,去补一下bitset的接口(零碎点那个文档里)

#include
 using namespace std;
 pairx[3001];
 struct node{
  int x,y;
  double dis;
 };
 node t[10000001];
 bitset<3001>ans[3001];
 ​
 double distance(pairx,pairy){
  return sqrt((x.first-y.first)*(x.first-y.first)+(x.second-y.second)*(x.second-y.second));
 }
 ​
 bool com(node a,node b){
  return a.dis>b.dis;
 }
 ​
 ​
 int main(){
  int n;
  cin>>n;
  ans[0].reset();
  for(int i=1;i<=n;i++){
  cin>>x[i].first>>x[i].second;
  ans[i].reset();
  }
  int num=0;
  for(int i=1;i<=n;i++){
  for(int j=i+1;j<=n;j++){
  t[num].x=i;
  t[num].y=j;
  t[num].dis=distance(x[i],x[j]);
  num++;
  }
  }
  sort(t,t+num,com);
  for(int i=0;i  int x=t[i].x;
  int y=t[i].y;
  if((ans[x]&ans[y])!=0){
  printf("%.8lf",t[i].dis/2);
  break;
  }
  ans[x].set(y,1);
  ans[y].set(x,1);
 
  }
  return 0;
 }

月月查华华的手机 (nowcoder.com)

题意:判断序列b是否为a的子序列(不连续)

这题我看到的时候居然想上kmp,艹,绝了,kmp是匹配连续子串,这个是不连续序列,其实就是双指针,但是,这题数据范围很大,所以如过对每个目标串都用一次双指针,就t了。

因此这里用了一个预处理,记录下每个位置,其后面每个字母第一次出现的位置,从后往前扫一遍就有了,感觉有点像ccpc网络赛的那个字符串dp的签到题(一模一样好伐)。

 #include
 using namespace std;
 ​
 int x[1000001][30];
 int last[30];
 ​
 int main(){
  string a;
  cin>>a;
  memset(last,-1,sizeof(last));
  for(int i=a.size()-1;i>=0;i--){
  for(int k=0;k<26;k++){
  x[i][k]=last[k];
  }
  last[a[i]-'a']=i;
  }
  int t;
  cin>>t;
  while(t--){
  string b;
  cin>>b;
  int pos=last[b[0]-'a'];
  int beg=pos;
  if(pos<0){
  cout<<"No"<  continue;
  }
  int flag=1;
  for(int i=1;i  pos=x[pos][b[i]-'a'];
  if(pos<0){
 // pos=x[beg][b[0]-'a'];//这里就是因为没想明白串和序列,想回退
 // beg=pos;
  if(pos<0){
  flag=0;
  cout<<"No"<  break;
  }
  //i=0;
  }
  }
  if(flag==1){
  cout<<"Yes"<  }
  }
  return 0;
 }

Problem - 484A - Codeforces

题意:找l-r内二进制1数量最多的数

位运算+贪心,因为数据范围太大,必不可能遍历,所以考虑贪心,把左右边界都变为二进制,把左边界为0的二进制位一个个改成1,看是否还小于右边界即可。tql,我自己想绝对想不出来,但是实现是我自己写的,我也算是稍微了解一些位运算了吧(

 #include
 using namespace std;
 #define ll long long
 int main(){
  int t;
  cin>>t;
  while(t--){
  ll l,r;
  cin>>l>>r;
  ll ans=l;
  for(ll i=1;i<=r;i<<=1){
  if((l&i)==0){
  ans+=i;
  if(ans>r){
  ans-=i;
  break;
  }
  }
  }
  cout<

兔子的区间密码 (nowcoder.com)

题意:求l-r内两个数的异或的最大值

找到l,r的第一个不一样的二进制位,从这位开始后面可以保证一个数全是1,另一个全是0.

 #include
 using namespace std;
 #define ll long long
 int main(){
  int t;
  scanf("%d",&t);
  while(t--){
  ll a,b;
  scanf("%lld %lld",&a,&b);
  int i=63;
  for(;i>=0;i--){
  if((a>>i)!=(b>>i)){
  break;
  }
  }
  printf("%lld\n",(1LL<  }
  return 0;
 }

位运算:一位一位去考虑


递归与分治

表达式计算4 (nowcoder.com)

题意就跟标题一样,计算表达式,当时正好数据结构也布置了一个类似的作业,思路是每一次都找到运算级最低的那个符号,将表达式分为两个部分,分别计算。

 #include
 using namespace std;
 string a;
 //string转int
 int num(int l,int r){
  int ans=0;
  for(int i=l;i<=r;i++){
  ans*=10;
  ans+=a[i]-'0';
  }
  return ans;
 }
 //计算l到r的计算式
 int calc(int l,int r){
  int pos1=-1,pos2=-1,pos3=-1;
  int cnt=0;
  //找到不在括号里的优先级最低的运算符的位置
  for(int i=l;i<=r;i++){
  if(a[i]=='('){
  cnt++;
  }
  if(a[i]==')'){
  cnt--;
  }
  if(cnt==0){
  if(a[i]=='+'||a[i]=='-'){
  pos1=i;
  }
  if(a[i]=='*'||a[i]=='/'){
  pos2=i;
  }
  if(a[i]=='^'){
  pos3=i;
  }
  }
  }
  //如果没找到运算符
  if(pos1==-1&&pos2==-1&&pos3==-1){
  //要么是被括号整体括起来了
  //注:后面两个else if是为了排除多余的括号
  if(cnt==0&&a[l]=='('){
  return calc(l+1,r-1);
  }else if(cnt<0&&a[l]=='('){
  return calc(l,r-1);
  }else if(cnt>0&&a[r]==')'){
  return calc(l+1,r);
  }
  //要么是就是一个数字
  return num(l,r);
  }
  //+ -优先级最低,先判断
  if(pos1!=-1){
  if(a[pos1]=='+'){
  return calc(l,pos1-1)+calc(pos1+1,r);
  }else{
  return calc(l,pos1-1)-calc(pos1+1,r);
  }
  }
  //然后是* /
  if(pos2!=-1){
  if(a[pos2]=='*'){
  return calc(l,pos2-1)*calc(pos2+1,r);
  }else{
  return calc(l,pos2-1)/calc(pos2+1,r);
  }
  }
  //最后是乘方
  if(pos3!=-1){
  return pow(calc(l,pos3-1),calc(pos3+1,r));
  }
 }
 ​
 int main(){
  cin>>a;
  cout<  return 0;
 }

1027-kotori和糖果_2021秋季算法入门班第二章习题:递归、分治 (nowcoder.com)

题意:共n堆糖果,一堆一个,合并两堆数量不一样的花费1,求最少总花费

这题本来是个很简单的记忆化搜索,但是我没想清楚应该返回什么,我本来想着返回两端的长度,但是后来转念一想,不对啊,有了n两端长度不是都有了吗,所以应该返回的是形成这两端需要的操作数。

#include
using namespace std;
typedef long long ll;
map mp;
ll getans(ll n){
if(n==0) return 0;
if(mp.count(n)) return mp[n];
if(n&1){
mp[n]=2*getans(n/2);
}else{
mp[n]=getans(n/2)+getans(n/2-1)+1;
}
return mp[n];
}
int main(){
ll t;
scanf("%lld",&t);
while(t--){
ll n;
scanf("%lld",&n);
if(n==0)puts("0");
else printf("%lld\n",getans(n-1));
}
}


二分、三分、01分数规划

艹,我记得我写完这一部分的了,但是好像关电脑前忘了保存,然后就没了,心态爆炸,再写一遍,呜呜呜

小咪买东西 (nowcoder.com)

01分数规划经典题目,题意:给n个物品,每一个物品都有一个价值和花费,求买k个的最大总价值(val)和总花费之比(cos)

思路:我们假设这个最大比值是x,那么比x小的比值一定也存在这样的方案,比x大的比值一定不存在这样的方案,那么我们就可以考虑二分,对于一个比值num来说,如果可行,一定存在一个方案使得val/cos>=num-->val-numcos>=0;因此我们在判断的时候把所有val-numcost最大的k个值算在内,如果这样都不行那就是真的不行。

#include
using namespace std;
#define ll long long
struct node{
ll c,v,mar;
};
ll n,m;
node x[10001];
bool com(node a,node b){
return a.mar>b.mar;
}
bool fun(ll a){
ll num=0;
for(ll i=0;i x[i].mar=x[i].v-a*x[i].c;
}
sort(x,x+n,com);
ll sum=0;
for(ll i=0;i sum+=x[i].mar;
}
if(sum<0){
return false;
}else{
return true;
}
}
int main(){
ll t;
cin>>t;
while(t--){
cin>>n>>m;
for(ll i=0;i cin>>x[i].c>>x[i].v;
}
ll l=0,r=1e8+1;
ll mid=0;
while(l mid=(l+r+1)/2;
if(fun(mid)){
l=mid;
}else{
r=mid-1;
}
}
cout< }
return 0;
}

gpa (nowcoder.com)

和上一题差不多,就是把最大值公式变了一下,我们一样做

#include
using namespace std;
#define INF 0x3f3f3f3f
#define ll double
struct node{
double a,b,tem;
};
node x[100001];
int n,m;
bool com(node a,node b){
return a.tem}
bool fun(ll a){
for(int i=0;i x[i].tem=x[i].a*(x[i].b-a);
}
sort(x,x+n,com);
for(int i=0;i if(x[i].tem<0){
x[i].tem=-INF;
}
}
ll sum=0;
for(int i=0;i if(x[i].tem==-INF){
continue;
}
sum+=x[i].tem;
}
if(sum<0){
return false;
}else{
return true;
}
}
int main(){
cin>>n>>m;
for(int i=0;i cin>>x[i].a;
}
for(int i=0;i cin>>x[i].b;
}
double l=0,r=1e11+1;
while(r-l>1e-6){//这里答案是小数,所以我们用控制精度的方法
double mid=(l+r)/2;
if(fun(mid)){
l=mid;
}else{
r=mid;
}
}
printf("%.6lf\n",l);
return 0;
}


堆栈、队列、单调栈、单调队列

[NOIP2016]蚯蚓 (nowcoder.com)

题意:给你n个数,每次会将一个数分割成比例为定值的两个数,求m次分割怎么让每个数尽可能小,每个数还会随时间增长一定值。

这题本来觉得没啥难的,优先队列嘛,谁不会啊(),但是看了眼数据范围,完蛋,会t,没办法,只能听雨巨讲了。

思路真的很巧妙,假设我们将最初的序列排序,拆分之后将两段分别放进两个队列里面,因为我们每次拆分的一定都比上一次小(或者一样)因此拆分后的两段一定也比先前的两段小,所以我们后放入队列的一定比先放入的小,这样就保证了有序,每次选择最大的时候只要去找三个队列的头即可。tql,未曾设想的道路。

但是这个输出要求就很恶心,我好不容易写完,你非要在输出上折磨我是什么意思

#include
#include
#include
using namespace std;
#define ll long long
int main() {
queueq[3];
int x[100001];
ll n, m, Q, u, v, t;
cin >> n >> m >> Q >> u >> v >> t;
double p = (double)u / v;
for (int i = 0; i cin >> x[i];
}
sort(x, x + n, greater());
for (int i = 0; i q[0].push(x[i]);
}
int now = 0;
while (now int mn = -0x3f3f3f3f, maxindex=-1;
for (int i = 0; i <3; i++) {
if (!q[i].empty() && q[i].front() > mn) {
mn = q[i].front();
maxindex = i;
}
}
if (maxindex==-1) {
break;
}
mn += now * Q;
q[maxindex].pop();
q[1].push((int)(u * mn/v) - now * Q-Q);
q[2].push(mn - (int)(u * mn/v) - now * Q-Q);

if ((now+1) % t == 0) {
cout < }
now++;
}
cout < now=1;
while (!q[0].empty() || !q[1].empty() || !q[2].empty()) {
int mn = -0x3f3f3f3f, maxindex=-1;
for (int i = 0; i <3; i++) {
if (!q[i].empty() && q[i].front() > mn) {
mn = q[i].front();
maxindex = i;
}
}
if (maxindex==-1) {
break;
}
if(now%t==0){
cout < }
now++;
q[maxindex].pop();
}
return 0;
}

Sliding Window (nowcoder.com)

 

动态维护一个在i-k~i之间可能成为答案的队列。

以最大值为例,如果后一个比前一个大,那么前一个就失去了成为答案的机会,就可以出队了,反之就不出队,但是当这个值的位置比区间的左端点还小的时候也要出队,本来我想用队列存数据的,但是雨巨点醒了我,存数据的话还要直到下标,所以我们直接把下标存起来,到原数组里找对应的数据即可。

第一次用对拍,有点爽,第一次交的时候wa在了长度为1的时候。

#include
using namespace std;
int x[1000011];
int main(){
// freopen("a.in","r",stdin);
// freopen("std.out","w",stdout);
int n,k;
cin>>n>>k;
for(int i=0;i cin>>x[i];
}
if(n==1){
cout< return 0;
}
dequeq;
// q.push_back(0);第一次wa在这.以后别tm提前插入行不行,对拍的时候是很爽,但是写起来很麻烦
for(int i=0;i while(!q.empty()&&x[q.back()]>x[i]){
q.pop_back();
}
q.push_back(i);
if(q.front()<=i-k){
q.pop_front();
}
if(i+1>=k){
cout< }
}
cout< q.clear();
for(int i=0;i while(!q.empty()&&x[q.back()] q.pop_back();
}
q.push_back(i);
if(q.front()<=i-k){
q.pop_front();
}
if(i+1>=k){
cout< }
}
return 0;
}

Largest Rectangle in a Histogram (nowcoder.com)

单调栈的板子题,所谓单调栈就是我们维护一个单调的栈,每当有新数据进来时,如果它破坏了原有的单调性,我们就一直出栈直到单调为止。

题意:给你一串高度不等高的等宽柱子,求能够在里面划出的最大的矩形的面积。

思路:我们存下每个柱子往左能够延伸的最大长度,如果新加的柱子比之前的高,那它的最大宽度就是1,如果新加的柱子比之前的矮,那我们在出栈的过程中把每一个出栈的柱子的往左延伸的最大长度相加得到的就是这个新柱子的最大长度,当然,如果一个柱子出栈了,就说明它不可能再向右延申了,这时我们用高度×它能向左延申的最大长度就是一个可能的最大面积。

#include
using namespace std;
#define ll long long
int x[100001];
int num[100001];//记录每个柱子能够向左延伸的最大长度
int main(){
int n;
while(cin>>n&&n){
for(int i=1;i<=n;i++){
cin>>x[i];
}
stackstk;
ll ans=0;
x[++n]=0;
for(int i=1;i<=n+1;i++){
ll temp=0;
while(!stk.empty()&&x[i]<=x[stk.top()]){
temp+=num[stk.top()];
ans=max(ans,temp*x[stk.top()]);
stk.pop();
}
stk.push(i);
num[stk.top()]=temp+1;
}
cout< }
return 0;
}



推荐阅读
  • 每日精选Codeforces训练题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)
    题目涉及三种不同类型的算法问题:1119E(贪心算法)、821C(栈模拟)和645D(拓扑排序)。其中,1119E的问题背景是有n种不同长度的棍子,长度分别为2^0, 2^1, …, 2^(n-1),每种棍子的数量为a[i]。任务是计算可以组成的三角形数量。根据三角形的性质,任意两边之和必须大于第三边。该问题可以通过贪心算法高效解决,通过合理选择棍子组合来最大化三角形的数量。 ... [详细]
  • 在2021-2022 ACM集训队月度编程挑战赛第二轮中,题目“最大值与最小值的选择”要求参赛者处理一个包含n个元素的数组,并给定一个整数k。任务是通过选择特定的子数组,计算并返回这些子数组的最大值和最小值之间的差值。该问题考验了选手对数组操作和优化算法的理解与应用能力。 ... [详细]
  • 本周课程涵盖了高精度计算、前缀和及差分技术。在高精度计算部分,我们将探讨如何处理任意进制的数值运算,包括但不限于正数的加法、减法和乘法。通过调整基数,可以灵活应对不同进制的需求。前缀和与差分技术则主要用于高效解决数组和区间查询问题,提升算法性能。 ... [详细]
  • Prim算法在处理稠密图时表现出色,尤其适用于边数远多于顶点数的情形。传统实现的时间复杂度为 \(O(n^2)\),但通过引入优先队列进行优化,可以在点数为 \(m\)、边数为 \(n\) 的情况下显著降低时间复杂度,提高算法效率。这种优化方法不仅能够加速最小生成树的构建过程,还能在大规模数据集上保持良好的性能表现。 ... [详细]
  • 本文介绍了UUID(通用唯一标识符)的概念及其在JavaScript中生成Java兼容UUID的代码实现与优化技巧。UUID是一个128位的唯一标识符,广泛应用于分布式系统中以确保唯一性。文章详细探讨了如何利用JavaScript生成符合Java标准的UUID,并提供了多种优化方法,以提高生成效率和兼容性。 ... [详细]
  • 探索偶数次幂二项式系数的求和方法及其数学意义 ... [详细]
  • C++入门必备:首个博客知识点汇总
    本文总结了C++初学者需要掌握的关键知识点,特别强调了成员类型的区分。其中,protected成员与private成员在本类中的作用相同,但protected成员允许派生类的成员函数访问,而private成员则不允许。此外,文章还介绍了其他重要的C++基础概念,如类的构造函数、析构函数以及继承机制,为初学者提供了一个全面的学习指南。 ... [详细]
  • 在SWUSTOJ #1063中,题目要求对带权重的有向图进行算法计算与分析。假设图G使用邻接矩阵存储,任务是计算图中的最大权值和最小权值,并确定对应的有向边。输入数据的第一行包含一个整数n,表示图中节点的数量。随后的输入将提供图的边及其权重信息。通过该算法,可以有效地找出图中的关键路径和最短路径,为图论问题的解决提供重要参考。 ... [详细]
  • HDU1176:免费馅饼问题的动态规划解法分析
    题目“免费馅饼”通过动态规划方法进行了解析。该问题的时间限制为 Java 2000ms 和其他语言 1000ms,内存限制为 Java 65536K 和其他语言 32768K。本文详细探讨了如何利用动态规划算法高效求解此问题,并对算法的时间复杂度和空间复杂度进行了深入分析。此外,还提供了具体的实现步骤和代码示例,帮助读者更好地理解和应用这一方法。 ... [详细]
  • 开发心得:成为SGU475智能筏工的策略与技巧 ... [详细]
  • 本文详细解析了九度编程平台上的斐波那契数列高效算法挑战(题目编号:1387)。该挑战要求在1秒的时间限制和32兆的内存限制下,设计出高效的斐波那契数列计算方法。通过多种算法的对比和性能分析,本文提供了优化方案,帮助参赛者在限定资源条件下实现高效计算。 ... [详细]
  • BZOJ 1835: 基站位置选择问题(动态规划与线段树优化) ... [详细]
  • SRM 553:深入解析供应链管理系统的最新进展与应用本文详细探讨了供应链管理系统(SCM)的最新发展及其在实际应用中的影响。通过对当前技术趋势的分析,文章揭示了 SCM 在提高效率、降低成本和增强透明度方面的关键作用。此外,还介绍了几种创新的 SCM 解决方案,如区块链技术和人工智能的应用,以及这些技术如何帮助企业更好地应对市场变化和挑战。 ... [详细]
  • 在解决区间相关问题时,我发现自己经常缺乏有效的思维方式,即使是简单的题目也常常需要很长时间才能找到解题思路,而一旦得到提示便能迅速理解。题目要求对一个包含n个元素的数组进行操作,并给出一个参数k,具体任务是…… ... [详细]
  • 本文探讨了在形状类族中应用纯虚函数的设计模式及其解析方法。通过定义一个基类 `Shape`,其中包含一个纯虚函数 `area()`,实现了多态性和代码的灵活性。该设计使得派生类能够根据具体的形状计算面积,从而提高了代码的可扩展性和复用性。示例代码展示了如何利用纯虚函数实现这一机制。 ... [详细]
author-avatar
半夏✔
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有