-
算法竞赛(差分)(上午)
初始化
#include <algorithm>
int arr[100];
std::fill(arr, arr + 100, 0);
//比memset更高效
int arr[100] = {}; // 所有元素都初始化为 0
栈溢出
为局部变量每次运行时都在运行栈中分配,如果数组很大,结果会造成运行栈溢出,自然就运行不了
另外,使用全局变量只是在静态区内分配,同样也有溢出的问题,显然你的数组需要的空间还没有到这么多
//作为全局变量,能运行
int a[1010][1010];
//作为局部变量,能运行,不能输入也不能输出
最大字段和(分治)
p1115
1e-9 表示科学记数法中的 10 的负九次方,即 0.000000001
不是-10^9;
#include<bits/stdc++.h>
using namespace std;
int n;
int a,b;
int ans=1e-9;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a;
if(i==0)b=a;
else
{
b=max(a,b+a);
}
ans=max(ans,b);
}
cout<<ans;
return 0;
}
-
比赛团队赛3+算法竞赛(差分和前缀和)
借教室 差分+二分
https://www.luogu.com.cn/problem/solution/P1083
int 大概在2.15e9
所以本题我们要开longlong
比较难想的是我们要而二分订单数量,这有一个性质,订单数量数轴,如果前面的点不符合,后面一定不符合。
质检员
https://www.luogu.com.cn/problem/P1314
#include<bits/stdc++.h>
#define ll long long
#define R register int
#pragma GCC optimize(3)//O3优化
using namespace std;
ll n,m,s,l,r,mid,ans;//朴素定义,
ll w[200010],v[200010],le[200010],ri[200010],ss;
ll Min=1e15; //记录结果
ll q[200010],p[200010]; //前缀和记录
//q记录从0~i有几个符合题意的源石,p记录从0~i符合题意的石头的价值之和
int main()
{
scanf("%lld%lld%lld",&n,&m,&s);
for(R i=1;i<=n;i++)
{
scanf("%lld%lld",&w[i],&v[i]);
r=max(r,w[i]);//右边界设为最大的w[i],应该是显然对的……当然如果不放心开到1<<30也没问题
}
for(R i=1;i<=m;i++) //读入m个区间
scanf("%lld%lld",&le[i],&ri[i]);
while(l<=r)
//这里取等了
{
ans=0,mid=(l+r)>>1;
for(R i=1;i<=n;i++) //循环更新前缀和数组
{
if(w[i]>mid)
q[i]=q[i-1]+1,p[i]=p[i-1]+v[i];
//q存前i个数量和,p存前i个价值和。二分W(所求)
//我们在求区间和所以用前缀和优化
else
q[i]=q[i-1],p[i]=p[i-1];
}
for(R i=1;i<=m;i++) //计算一下Y,也就是Y1+Y2+……+Yn
ans+=(q[ri[i]]-q[le[i]-1])*(p[ri[i]]-p[le[i]-1]);
//每个区间的数量和×价值和即yi
ss=s-ans; //这里先不要绝对值,要利用原数决定怎么改l和r的值
//ans y大于s时,增大w减小y,使y-s绝对值减小
//ans y小于s时,减小w增大y,使y-s绝对值增大
if(ss<0)l=mid+1; //小于0说明假定的W小了,扩大l的值
else r=mid-1; //否则缩小r的值
Min=min(Min,abs(ss)); //更新求得的最小值
}
printf("%lld",Min);
}
算法竞赛 排序和排列
结构体
//这个相当于定义结构体同时,定义了结构体变量s1,s2;
//补充)sort左闭右开
https://blog.csdn.net/m0_51064412/article/details/130352792
排列 next_permutation(s.begin(),s.end(),cmp)
prev.permutation求前一个排列组合
string s="abc";
do{
cout<<s<<endl;
}while(next_permutation(s.begin(),s.end()));
//输出第n个排列,n=1654
do{
if(n==1654){
for(int i=0;i<7;i++)
cout<<a[i];
cout<<endl;
break;
}
n++;
}while(next_permutation(a,a+7));
//序列中有重复元素会去重
//结构体需要定义如何比较
struct test{//结构体test
int val;
};
bool cmp(test t1,test t2){//自定义的排列
return t1.val<t2.val;
}
int main(){
test t[4];//结构体数组
t[0].val=1;
t[1].val=2;
t[2].val=3;
t[3].val=4;
do{
for(int i=0;i<4;i++){//打印排列
cout<<t[i].val<<' ';
}
cout<<endl;
//vector
#include<iostream>
#include<vector> //使用vector需要导入的头文件
#include<algorithm>//使用 next_permutation()和sort()需要导入的头文件
using namespace std;
int main(){
vector<int> v;//定义一个int型的vector
v.push_back(1);//在尾部插入数据1
v.push_back(2);
v.push_back(3);
v.push_back(4);
do{
for(int i=0;i<v.size();i++){//打印排列
cout<<v[i]<<' ';
}
cout<<endl;
}while(next_permutation(v.begin(),v.end()));//获取下一个排列
//这个需要用begin和end,不能用名代表地址
}
-
vj团队3补题
跳圆(思维)
题意:一个环从0到p-1,从0开始每次跳1,2,3,···,n-1,n步,问跳n步之后会有多少个位置访问过。
1 突破点是圆的循环性?猜想有一个点会回到原点,因为数据太大没法暴力
2 有效步数>1,<=p
思路:弄一个vis数组,表示访问过的点,注意p为1e7,数组开大点(不然容易RE)
然后若n>2p,2p次后又一定回到点原点,然后2p+1,2p+2步的效果相当于1,2步(%p就知道
了)1+2+3+...+2p)=1+2p)*2p/2一定能整除p
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+10;
int st[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int p,n;
cin>>p>>n;
int t=0;
st[0]=1;
for(int i=1;i<=min(n,2*p);i++)
{
t=(t+i)%p;
st[t]=1;
}
int res=0;
for(int i=0;i<p;i++)
res+=st[i];
cout<<res<<endl;
return 0;
}
重叠部分内接圆面积最大值
cmath头文件里面定义了y1!!!
所以y1为全局变量时会报错!!!
abs()和fabs();整型和浮点型
不会计算重叠的宽和高
向量缩放求解坐标
不要局限于列方程求解
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+10;
signed main(){
double x1,y1,r1,x2,y2,r2;
cin>>x1>>y1>>r1;
cin>>x2>>y2>>r2;
double c=(double)sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); //两个圆心的距离
double s=(double)(r1+r2-c)/2; //半径
double x=double (x2-x1)*(c-r2+s)/c;
double y=double (y2-y1)*(c-r2+s)/c;
x+=x1,y+=y1;
printf("%.15lf %.15lf %.15lf",x,y,s);
return 0;
}
只进行列变换能否连到一起
关键:只有四类情况,双#,双。,和上下各一个,双#能连接两部分,所以有后两个就必须有双#,并且结果输出时,因为不能连成一片的结果好判断,所以写判断否定情况
#include<bits/stdc++.h>
using namespace std;
double x1,y11,x2,y2,r1,r2;
int main()
{int numj=0,numx=0,nums=0,numd=0;
string s1,s2;
cin>>s1;
cin>>s2;
for(int i=0;i<s1.size();i++)
{
if(s1[i]=='#'&&s2[i]=='#')
numj++;
else if(s1[i]=='#'&&s2[i]=='.')
nums++;
else if(s1[i]=='.'&&s2[i]=='#')
numx++;
else if(s1[i]=='.'&&s2[i]=='.')
numd++;
}
int nums1=nums,numj1=numj,numx1=numx,numd1=numd;
if(numj==0&&numx>0&&nums>0)
cout<<"NO"<<endl;
else
{cout<<"YES"<<endl;;
while(nums1--)cout<<"#";
while(numj1--)cout<<"#";
while(numx1--)cout<<".";
while(numd1--)cout<<".";
cout<<endl;
while(nums--)cout<<".";
while(numj--)cout<<"#";
while(numx--)cout<<"#";
while(numd--)cout<<".";
}
}```