碰撞2
在 xy坐标系中有 N 个人,第 i 个人的位置是 (Xi,Yi),并且每个人的位置都不同。
我们有一个由 L
和 R
组成的长为 N 的字符串 S,Si= R
代表第 i 个人面向右,Si= L
代表第 i 个人面向左。
现在所有人开始朝着他们各自面向的方向走,即面向右 x 就增,面向左 x 就减。
例如,当 (X1,Y1)=(2,3),(X2,Y2)=(1,1),(X3,Y3)=(4,1),S=RRL
时,人们的移动如图。
我们把两个人对向行走到一个位置称为一次碰撞。请问如果人们可以无限走下去,会有人产生碰撞吗?
输入格式
第一行一个整数 N;
接下来 N 行,每行两个整数 X 和 Yi,表示第 i 个人的位置;
最后一行是一个由 L
和 R
组成的长为 N 的字符串 S。
输出格式
如果会有碰撞,输出 Yes
,否则输出 No
。
样例输入 1
3
2 3
1 1
4 1
RRL
样例输出 1
Yes
样例输入 2
2
1 1
2 1
RR
样例输出 2
No
样例输入 3
10
1 3
1 4
0 0
0 2
0 4
3 1
2 4
4 2
4 4
3 3
RLRRRLRLRR
样例输出 3
Yes
数据规模
所有数据保证 2≤N≤2×10^5,0≤Xi≤10^9,0≤Yi≤10^9。
#include<bits/stdc++.h>
using namespace std;
int N,ans,ly=-1,lh;
struct node
{
int x,y,h;
bool operator < (const node & a) const
{
if(y!=a.y)return y<a.y;
return x>a.x;
}
}peo[200005];
priority_queue<node>w;
int main()
{
cin>>N;
for(int i=1;i<=N;i++)
{
cin>>peo[i].x>>peo[i].y;
}
for(int i=1;i<=N;i++)
{
char c;
cin>>c;
if(c=='R')peo[i].h=1;
else peo[i].h=-1;
w.push(peo[i]);
}
while(!w.empty())
{
node T=w.top();
// cout<<T.x<<" "<<T.y<<" "<<T.h<<endl;
w.pop();
if(T.y==ly)
{
if(lh==1&&T.h==-1)
{
ans=1;
break;
}
}
ly=T.y;
lh=T.h;
}
if(ans)cout<<"Yes\n";
else cout<<"No\n";
}
#671. 优美!最长上升子序列
多组数据。
每组将给定一个数组。派派希望从中选择一个递增的子序列,越长越好。
但派派认为,这样选出来的子序列依然不够「优美」,形式化的讲,派派希望选择的下标(从 11 开始)需要满足
i1∣i2∣i3∣⋯∣ik
其中 a|b表示整除, 即 a是 b 的约数。
请你帮助派派完成任务吧!
注:子序列的含义不再赘述。
输入格式
第一行一个整数 T,表示接下来有 T 组数据。
每组数据包含两行,第一行包含一个整数 N。
随后一行,包含 N个整数,表示原数组 {A}。
输出格式
对于每组数据,输出一行,包含一个数,表示能选出的「优美」的最长上升子序列长度。
数据规模
- 1≤T≤100
- 1≤N≤10^6,但保证 ∑i=1TNi≤10^6
- 1≤Ai≤10^9
样例输入
4
4
1 4 6 7
2
2 2
10
1 2 3 4 5 6 7 8 9 10
10
10 9 8 6 5 2 3 1 2 1
样例输出
3
1
4
1
解释:
对于第一组数据,能选择的「优美」最长上升子序列为 {A1,A2,A4}={1,4,7}。
对于第三组数组,选择 {A1,A2,A4,A8}={1,2,4,8}。
对于第四组数据,可选择的「优美」最长上升子序列长度为 1。
#include<bits/stdc++.h>
using namespace std;
int T,N,a[1000006],ans;
int main()
{
cin>>T;
while(T--)
{
cin>>N;
ans=1;
vector<int>dp(N+1,1);
for(int i=1;i<=N;i++)
{
cin>>a[i];
}
for(int i=1;i<=N;i++)
{
for(int j=i*2;j<=N;j+=i)
{
if(a[j]>a[i])dp[j]=max(dp[j],dp[i]+1);
ans=max(ans,dp[j]);
}
}
cout<<ans<<endl;
}
}
#706. 巨大的牛棚
题目描述
农夫约翰想要在他的正方形农场上建造一座正方形大牛棚。他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方。我们假定,他的农场划分成 n * n
的方格。输入数据中包括有树的方格的列表。你的任务是计算并输出,在他的农场中,不需要砍树却能够修建的最大正方形牛棚。牛棚的边必须和水平轴或者垂直轴平行。 考虑下面的方格,它表示农夫约翰的农场,‘.'表示没有树的方格,‘#'表示有树的方格
........
.#...#..
........
........
........
..#.....
........
........
那么最大的牛棚是5*5
的。
输入描述
第一行输入一个正整数 n(1≤n≤1000)代表农场的大小,一个正整数T(1≤T≤n∗n), 接下来 T行,每行2个整数,代表有树的格子的横纵坐标,保证任意两个树格子不相同
输出描述
输出一个正整数代表牛棚的最大边长
样例输入
8 3
2 2
2 6
6 3
样例输出
5
#include<bits/stdc++.h>
using namespace std;
int T,N,mapp[1003][1003],dp[1003][1003],ans;
int main()
{
cin>>N>>T;
for(int i=1;i<=T;i++)
{
int a,b;
scanf("%d%d",&a,&b);
mapp[a][b]=1;
}
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
if(!mapp[i][j])
{
dp[i][j] = min(min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1])+1;
}
ans=max(ans,dp[i][j]);
}
}
printf("%d\n",ans);
}
#708. 高利贷
19岁的大学生小 L 家里情况不好,每月固定生活费不足以买一部苹果手机。当他得知有贷款机构可以贷小额贷款并且可以分期等额还款,每月只需要还几百块时,在虚荣心的驱使下他开始自己的贷款之旅。
贷款机构声称利率按月累计,贷款人在贷款期间每月偿还固定的分期付款金额。
给出小 L贷款的原值为 n,分期付款金额 m 和分期付款还清贷款所需的总月数 k,求该贷款的月利率 p。
输入格式
三个用空格隔开的正整数 n,m,k,含义如上述所示。
输出格式
一个实数 p,表示该贷款的月利率(用小数表示),和标准输出绝对值不超过10^−6即可。
数据范围
1≤n,m≤10^6,1≤k≤300
0≤p≤5,
n≤m×k
输入样例1
1000 1200 1
输出样例1
0.200000
输入样例2
1000 100 12
输出样例2
0.029229
样例解释
对于第一组样例,小 L 贷款了 1000 元,并在一个月后支付 1200 元还清了贷款。因此计算月利率 p的公式为 1000×(1+p)=1200或 1200/1+p=1000,求出 p=0.200000。
对于第二组样例,小 L 贷款了 1000元,并以每月支付 100元的方式在 12个月后还清了贷款。由于月利率的存在,他第 k个月偿还的金额只相当于 100/(1+p)^k 元的初始金额,且这12个月共偿还初始金额1000元,求出 p=0.029229。
#include<bits/stdc++.h>
using namespace std;
double n,m,k,l,r,mid,ans;
double sum(double p)
{
double a=m/(1+p),s=0;
for(int i=1;i<=k;i++)
{
s+=a;
a/=(1+p);
}
return s;
}
int main()
{
cin>>n>>m>>k;
l=0,r=5;
while(1)
{
mid=(l+r)/2;
double d=sum(mid)-n;
if(d<=1e-6&&d>-1e-6)break;
if(d<0)r=mid;
else l=mid;
}
cout<<fixed<<setprecision(6)<<mid;
}
背包
cc有一个背包,背包的体积为w,有n个物品,每一个物品的体积为ai
cc希望将其中的一些物品放入他的背包中,他希望这些物品的体积之和至少是背包体积的一半,并且不超过背包的体积,即 ⌈w/2⌉≤sum≤w
请你帮cc判断这些物品中有没有符合条件的物品组合,如果有输出"YES", 没有输出"NO"
cc至少会拿一个物品
输入格式
第一行给出测试样例个数T
对于每一个样例:
第一行给出一个n和一个w,n个物品,背包的总体积是w
第二行给出一个序列a1,...an,代表每一个物品的体积
输出格式
如果有请输出"YES", 没有输出"NO"
数据范围
1≤t≤1e4,1≤∑n≤2e5,1≤w≤1e18,0≤wi≤1e9
样例输入1
3
1 3
3
6 2
19 8 19 69 9 4
7 12
1 1 1 17 1 1 1
样例输出
YES
NO
YES
#include<bits/stdc++.h>
using namespace std;
long long w,T,N,a;
int main()
{
scanf("%lld",&T);
while(T--)
{
long long ans=0,sum=0;
scanf("%lld%lld",&N,&w);
long long m=(w%2==0?(w/2):(w/2+1));
for(int i=1;i<=N;i++)
{
scanf("%lld",&a);
if(a<=w&&a>=m)ans=1;
else if(a<m)sum+=a;
}
if(sum>=m)ans=1;
if(ans)printf("YES\n");
else printf("NO\n");
}
}
#732. 简单的异或问题
有一组整数 {0,1,2,…,2m−1}, 请从中选出 k 个数,使得这 k 个数的异或和为 n, 请输出最大的满足条件的 k。
输入格式
两个数 n 和 m, 其中 0≤n≤2m−1,1≤m≤60。
输出格式
输出最大的满足条件的 k。
样例输入
2 2
样例输出
3
样例解释
对于样例,我们可以选择 {0,1,3}。
#include<bits/stdc++.h>
using namespace std;
long long m,n,ans=1;
int main()
{
cin>>n>>m;
ans<<=m;
if(n==0&&m==1)cout<<1;
else if(n==0)cout<<ans;
else if(n==1&&m==1)cout<<2;
else cout<<ans-1;
cout<<"\n";
}
#734. 子串的循环挪动
给出一个字符串 s,你需要执行 m个任务。每个任务给出两个下标 li,ri和一个整数 ki(字符串的下标从 1 开始),表示你需要循环挪动 s 的子串 s[li...ri] ki次。请从前到后依次执行给出的每个任务。
字符串的循环挪动操作:将最后一个字符移到第一个字符的位置,并且将其他所有字符向右移一个位置。
比如:如果字符串 s 是 abacaba
,一个任务为 l1=3,r1=6,k1=1,那么答案为 abbacaa
。接下来一个任务为 l2=1,r2=4,k2=2,那么我们会得到 baabcaa
。
输入格式
第一行一个字符串 s,该字符串只包含小写英文字符。
第二行一个整数 m,表示任务个数。
接下来 m行每行有三个整数 li,ri和 ki。
输出格式
输出执行了 m 个任务后的最终的字符串 s。
样例输入
abacaba
2
3 6 1
1 4 2
样例输出
baabcaa
数据规模
对于所有数据保证,1≤|s|≤10000(|s| 表示字符串 s 的长度),1≤m≤300,1≤li≤ri≤|s|,1≤ki≤1000000。
#include<bits/stdc++.h>
using namespace std;
int N,l,r,k;
string s,st;
int main()
{
cin>>s;
cin>>N;
while(N--)
{
cin>>l>>r>>k;
k%=r-l+1;
st=s.substr(l-1,r-l+1);
for(int i=1;i<=k;i++)
{
int b=st.size();
if(b==1)break;
string t=st.substr(0,b-1);
char ch=st[b-1];
st=ch+t;
}
s.replace(l-1,r-l+1,st);
}
cout<<s<<endl;
}
#677. 弗拉德和糖果 II
不久前,弗拉德过生日,他收到了一包糖果。有 n种糖果,第 i 种糖果有 ai个(1≤i≤n)。
弗拉德决定每次只吃一个糖果。为了从吃东西中获得最大的乐趣,弗拉德不想连续吃两个相同类型的糖果。
帮助他弄清楚他是否可以在不连续吃两个相同的糖果的情况下吃掉所有的糖果。
简而言之,给定 n个正整数 ai,ai表示有 ai 个 i,找到是否存在一种序列,使得所有的数都用上,且不存在 i连续的情况
输入格式:
第一行,包含一个整数 n。 第二行,包含 n 个正整数。
输出格式:
输出一行,如果存在,输出YES
,否则输出NO
样例输入
2
1 1
样例输出
YES
说明
只有两种情况:
1.
1 2
2.
2 1
无论先吃哪种糖果,都能吃完且不连续吃相同类型的糖果
数据限制
对于 100% 的数据,保证 1≤n≤5000000,1≤ai≤2^30
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e17;
long long n,a[5000006],m,s[2],ans,b[2];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(s[0]+a[i]>=mod)
{
s[0]-=mod;
s[1]++;
}
s[0]=(s[0]+a[i])%mod;
s[1]+=a[i]/mod;
if(a[i]>a[m])m=i;
}
b[0]=a[m]%mod;
b[1]=a[m]/mod;
b[1]*=2;
if(b[0]*2>=mod)
{
b[0]-=mod;
b[1]++;
}
b[0]=(2*b[0])%mod;
if(s[1]>b[1])ans=1;
else if(s[1]==b[1]&&s[0]>=b[0]-1)ans=1;
if(ans)cout<<"YES\n";
else cout<<"NO\n";
}
#736. 上帝的集合
题目描述
现在上帝有一个空集合,现在他命令你为他执行下列三种操作 n 次,他每次会给你一个操作类型 op。
操作1:向集合中插入一个整数 x;
操作2:将集合中所有的数加上 x;
操作3:输出集合中最小的数,并从集合中将他删除,如果存在多个最小的整数,任意选择一个即可;
输入描述
第一行输入一个整数 n;
接下来的 n 行,每行的输入如下所示。第一个数代表 op,如果 op=1 或 op=2,第二个数代表 xi:
1 xi
2 xi
3
输出描述
如果 op=3,请输出集合中的最小值。
样例输入
7
1 2
1 1
3
1 3
2 5
3
3
样例输出
1
7
8
数据范围
2≤n≤10^6, 1≤xi≤10^12
#include<bits/stdc++.h>
using namespace std;
int n;
long long add;
struct ll
{
long long v;
ll* next;
}a[1000006];
ll* null=a+1000003;
int main()
{
a->next=null;
null->v=9876543210987654;
cin>>n;
int ti=0;
while(n--)
{
ti++;
int op;
long long x;
scanf("%d",&op);
if(op==1)
{
scanf("%lld",&x);
for(ll* i=a;i!=null;i=i->next)
{
if(x-add<=i->next->v)
{
a[ti].next=i->next;
a[ti].v=x-add;
i->next=a+ti;
break;
}
}
}
else if(op==2)
{
scanf("%lld",&x);
add+=x;
}
else
{
printf("%lld\n",a->next->v+add);
a->next=a->next->next;
}
}
}
三回文序列
给定一个长度为n的序列a。
我们定义三回文序列是形如的序列,例如:[1,1,1,2,2,1,1,1]是一个三回文序列,而[1,1,1,2,2,2,3,3,3],[1,1,2,2,1]都不是三回文序列。
现在,希望你找到序列a中最长的三回文序列的长度。
注意,k1,k2可以为0
输入格式
第一行给出一个数字T,表示T组测试用例
对于每一个测试用例
第一行给出序列的长度n
第二行给出序列a1,a2,a3...an
输出格式
对于每一个测试用例,输出最长的三回文序列的长度。
数据范围
1≤t≤2000,1≤∑n≤2e5,1≤ai≤26
样例输入
6
8
1 1 2 2 3 2 1 1
3
1 3 3
4
1 10 10 1
1
26
2
2 1
3
1 1 1
样例输出
7
2
4
1
1
3
#include<bits/stdc++.h>
using namespace std;
int T,N,f[200005][27],v[200005];
int main()
{
scanf("%d",&T);
while(T--)
{
int a,b,ans=1;
scanf("%d",&N);
memset(f,sizeof(f),0);
for(int i=1;i<=N;i++)
{
scanf("%d",&v[i]);
for(int j=1;j<=26;j++)f[i][j]=f[i-1][j];
f[i][v[i]]++;
}
v[N+1]=0;
for(int j=1;j<=26;j++)f[N+1][j]=f[N][j];
if(N==1||N==0)
{
cout<<N<<endl;
continue;
}
for(a=1;a<=26;a++)
{
int l=0,r=N+1,kl=0,kr=0;
for(int num=1;num<=N;num++)
{
while(kl<num&&l<r)
{
l++;
if(v[l]==a)kl++;
}
while(kr<num&&l<r)
{
r--;
if(v[r]==a)kr++;
}
if(kl!=num||kr!=num)break;
for(b=1;b<=26;b++)
{
if(l<r)ans=max(ans,f[r-1][b]-f[l][b]+2*num);
else ans=max(ans,2*num-1);
}
}
}
cout<<ans<<endl;
}
}