链接
A Exact Price
对n取余看是否为0,注意特判0.
B String Shifting
找最小,最大,我们发现他是有个环形的字符串那么我们可以把n个字符串提取出来,排序即可。
C - Doukasen
我们从两端往中间走,看那一端先到交界处这段就要向前走下一块,速度会变,到了交界处另一端减去当前时间走的即可(速度不变),所以我们只需要比较走过两端最后一块的时间为多长,取小的即可。长度用double用ll是不对的哦
ll n,m;
struct node
{
double a, b;
}q[MAX];
bool cmp(node a,node b){
return a.a<b.a;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>q[i].a>>q[i].b;
}
///sort(q+1,q+1+n,cmp);
ll l=1,r=n;
double sum=0.0;
while(l<=r){
if(l!=r){
double t1,t2;
t1=q[l].a*1.0/q[l].b;
t2=q[r].a*1.0/q[r].b;
//cout<<t1<< " "<< t2<<endl;
if(t1>t2){
sum+=t2*q[l].b;
q[l].a-=t2*q[l].b;
r--;
}else if(t2>t1){
sum+=q[l].a;
q[r].a-=t1*q[r].b;
l++;
}else if(t1==t2){
sum+=q[l].a;
l++;
r--;
}
}else {
sum+=q[l].a*1.0/2;
l++;r--;
break;
}
}
printf("%.20lf\n",sum);
}
D - Restricted Permutation
题意:
给出n个点,m个条件:
- 每个条件两个参数,a,b,意味着a在b,之前出现。
看完这个条件是不是想到了,前置条件,这不就是拓扑排序的意思吗?直接写;
ll n,m;
std::vector<ll> v[MAX];
ll in[MAX],out[MAX];
ll b[MAX],a[MAX];
priority_queue<ll,vector<ll>,greater<ll> >mx;
void topsort(){
for(ll i=1;i<=n;i++){
if(in[i]==0){
mx.push(i);
b[i]==1;
}
}
ll cnt=0;
while(!mx.empty()){
ll top = mx.top();
a[++cnt]=top;
mx.pop();
for(int i=0 ;i<v[top].size();i++){
ll j=v[top][i];
in[j]--;
if(b[j]==0&&in[j]==0){
b[j]=1;
mx.push(j);
}
}
}
if(cnt==n) {
for(int i=1;i<=n;i++) cout<< a[i]<<" ";
}else puts("-1");
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++){
ll x,y;
cin>>x>>y;
in[y]++;
out[x]++;
v[x].push_back(y);
}
topsort();
}
E - Placing Rectangles
题意:
很简单:就是给出你一个 n × m n\times m n×m的矩形,让你让三个面积为a,b,c的矩形,看看是否能够放进去。
分析:
如果我们放三个矩形在一个矩形中有多少种那?
我们画一下就知道了:
第一种三个横着的:
第二种三个竖着的:
第三种一个竖着两个横着:
第四种一个横着两个竖着:
好没了,就这四种,那么我们可以直接判断了,任意一种能放下就说明能放下,都放不下那就是放不下呗。
bool check1(ll a, ll b, ll c){
ll a1=(a+x-1)/x;
ll ty=y-a1;
ll b1=(b+ty-1)/ty;
ll c1=(c+ty-1)/ty;
if(b1+c1<=x) return 1;
a1=(a+y-1)/y;
ty=x-a1;
b1=(b+ty-1)/ty;
c1=(c+ty-1)/ty;
if(b1+c1<=y) return 1;
return 0;
}
ll a,b,c;
void solve()
{
cin>>x>>y>>a>>b>>c;
if(a+b+c>x*y) puts("No");
else{
///1
ll a1=(a+x-1)/x;
ll b1=(b+x-1)/x;
ll c1=(c+x-1)/x;
if(a1+b1+c1<=y){
puts("Yes");
return ;
}
///2
a1 = (a+y-1)/y;
b1 = (b+y-1)/y;
c1 = (c+y-1)/y;
if(a1+b1+c1<=x){
puts("Yes");
return ;
}
///3
if(check1(a,b,c)||check1(b,a,c)|| check1(c,b,a)){
puts("Yes");
return ;
}
puts("No");
}
}
F - Parenthesis Checking
题意:
给出长度为n的括号序列,对其进行q次操作:
- 1 l,r将l,r位置上的符号进行互换。
- 2 l,r询问l~r,是否是规范的序列。
分析:
我们可以采用分块来做,交换的话我们改变的是两个点,影响的是这两个点所在的 n \sqrt n n序列,询问,我们只需要看看两端即可。复杂度是 O ( n n ) O(n\sqrt n) O(nn)
string str;
ll n,m;
ll a[MAX],b[MAX];
void solve()
{
cin>>n>>m;
ll num = 0 ;
while(num*num <n) num++;
cin>>str;
for(int i=0;i*num<n;i++){
a[i] = 0;
b[i] = 0;
for(int j=0;j<num;j++){
if(str[i*num+j]=='(') a[i]++;
else {
a[i]--;
}
if(b[i] > a[i]){
b[i] = a[i];
}
}
}
ll l, r, op;
while(m--){
cin>>op>>l>>r;
l--;r--;
if(op==1){
swap(str[l],str[r]);
ll x = l / num;
a[x] = 0;
b[x] = 0;
for(int j=0;j<num;j++){
if(str[x*num+j]=='('){
a[x]++;
}else {
a[x]--;
}
if(b[x]>a[x]) b[x]=a[x];
}
x = r / num;
a[x] = 0;
b[x] = 0;
for(int j=0;j<num;j++){
if(str[x*num+j]=='('){
a[x]++;
}else {
a[x]--;
}
if(b[x]>a[x]) b[x]=a[x];
}
}else {
ll flag=0,sum=0;
if(l/num <r/num){
ll i = l/num;
for(int j=l%num;j<num;j++){
if(str[i*num+j]=='(') sum++;
else sum--;
if(sum<0) flag++;
}
for(int i=l/num+1;i<r/num;i++){
if(sum+b[i]<0) flag++;
sum+=a[i];
}
i=r/num;
for(int j=0;j<=r%num;j++){
if(str[i*num+j]=='(') sum++;
else sum--;
if(sum<0) flag++;
}
if(sum!=0) flag++;
}else {
ll i=l/num;
for(int j=l%num;j<=r%num;j++ ){
if(str[i*num+j]=='(') sum++;
else sum--;
if(sum<0) flag++;
}
if(sum!=0) flag++;
}
if(flag>0) puts("No");
else puts("Yes");
}
}
}