LOADING

加载过慢请开启缓存 浏览器默认开启

叫兽の窝

线段树板子题《最大数》

算法 2024/9/6

[JSOI2008] 最大数

题目描述

现在请求你维护一个数列,要求提供以下两种操作:

  1. 查询操作。

语法:Q L

功能:查询当前数列中末尾 $L$ 个数中的最大的数,并输出这个数的值。

限制:$L$ 不超过当前数列的长度。$(L > 0)$

  1. 插入操作。

语法:A n

功能:将 $n$ 加上 $t$,其中 $t$ 是最近一次查询操作的答案(如果还未执行过查询操作,则 $t=0$),并将所得结果对一个固定的常数 $D$ 取模,将所得答案插入到数列的末尾。

限制:$n$ 是整数(可能为负数)并且在长整范围内。

注意:初始时数列是空的,没有一个数。

输入格式

第一行两个整数,$M$ 和 $D$,其中 $M$ 表示操作的个数,$D$ 如上文中所述。

接下来的 $M$ 行,每行一个字符串,描述一个具体的操作。语法如上文所述。

输出格式

对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。

样例 #1

样例输入 #1

5 100
A 96
Q 1
A 97
Q 1
Q 2

样例输出 #1

96
93
96

提示

数据规模与约定

对于全部的测试点,保证 $1 \leq M \leq 2 \times 10^5$,$1 \leq D \leq 2 \times 10^9$。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
const int mod=1e9+7; 
struct ty
{
    int minv;
}tree[4*N];
void update(int id)
{
    tree[id].minv=max(tree[id*2].minv,tree[id*2+1].minv);
}
int query(int id,int l,int r,int ql,int qr)
{
    if(l==ql&&r==qr) return tree[id].minv;
    int mid=(l+r)>>1;
    if(qr<=mid) return query(id*2,l,mid,ql,qr);
    else if(ql>mid) return query(id*2+1,mid+1,r,ql,qr);
    else return max(query(id*2,l,mid,ql,mid),query(id*2+1,mid+1,r,mid+1,qr));
}
void change(int id,int l,int r,int pos,int val)
{
    if(l==r) tree[id].minv=val;
    else
    {
        int mid=(l+r)>>1;
        if(pos<=mid) change(id*2,l,mid,pos,val);
        else change(id*2+1,mid+1,r,pos,val);
        update(id);
    }
}
void solve()
{
    int n,m;
    cin>>n>>m;

    //build(1,1,n);
    int last=0;
    int idx=0;
    for(int i=1;i<=n;i++)
    {
        char op;
        cin>>op;
        if(op=='A') 
        {
            int x;
            cin>>x;
            change(1,1,n,idx+1,(x+last)%m);
            idx++;
        }
        else
        {
            int x;
            cin>>x;
            last=query(1,1,n,idx-x+1,idx);
            cout<<last<<endl;
        }

    }
}
signed main()
{
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
struct tr
{
    int l,r;
    int v;
}tree[4*N];
void build(int id,int l,int r)
{
    tree[id]={l,r};
    if(l==r) return;
    int mid=(l+r)>>1;
    build(id*2,l,mid);
    build(id*2+1,mid+1,r);
}
void update(int id)
{
    tree[id].v=max(tree[id*2].v,tree[id*2+1].v);
}
void change(int id,int pos,int val)
{
    if(tree[id].r==tree[id].l) tree[id].v=val;
    else
    {
        int mid=(tree[id].l+tree[id].r)>>1;
        if(pos<=mid) change(id*2,pos,val);
        else change(id*2+1,pos,val);
        update(id);
    }
}
int query(int id,int ql,int qr)
{
    if(tree[id].l==ql&&tree[id].r==qr) return tree[id].v;
    int mid=tree[id].l+tree[id].r>>1;
    if(qr<=mid)return query(id*2,ql,qr);
    else if(ql>mid) return query(id*2+1,ql,qr);
    else return max(query(id*2,ql,mid),query(id*2+1,mid+1,qr));
}
void solve()
{
    int n,m;
    cin>>n>>m;
    int idx=0,last=0;
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
        char op;
        int x;
        cin>>op>>x;
        if(op=='A')
        {
            change(1,idx+1,(x+last)%m);
            idx++;
        }
        else
        {
            last=query(1,idx-x+1,idx);
            cout<<last<<endl;
        }
    }
}
signed main()
{
    int t=1;
    while(t--)
    {
        solve();
    }
}
阅读全文

Codeforces Round 970 (Div. 3)

题解 2024/9/2

A. Sakurako’s Exam

题目

Today, Sakurako has a math exam. The teacher gave the array, consisting of $a$ ones and $b$ twos.

In an array, Sakurako must place either a ‘+’ or a ‘-‘ in front of each element so that the sum of all elements in the array equals $0$.

Sakurako is not sure if it is possible to solve this problem, so determine whether there is a way to assign signs such that the sum of all elements in the array equals $0$.

实现


  #include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
const int mod=1e9+7; 
void solve()
{
    int a,b;
    cin>>a>>b;
    int now=a+b*2;
    while(b>0 and now>=4)
    {
        b--;
        now-=4;
    }
    while(a>0 and now>=2)
    {
        a--;
        now-=2;
    }
    if(now==0) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}
signed main()
{
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

B. Square or Not

题目

A beautiful binary matrix is a matrix that has ones on its edges and zeros inside.

Today, Sakurako was playing with a beautiful binary matrix of size $r \times c$ and created a binary string $s$ by writing down all the rows of the matrix, starting from the first and ending with the $r$-th. More formally, the element from the matrix in the $i$-th row and $j$-th column corresponds to the $((i-1)*c+j)$-th element of the string.

You need to check whether the beautiful matrix from which the string $s$ was obtained could be squared. In other words, you need to check whether the string $s$ could have been build from a square beautiful binary matrix (i.e., one where $r=c$).

实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
void solve()
{
   int n;
   cin>>n;
   string s;
   cin>>s;
   if(sqrt(n)*sqrt(n)!=n) 
   {
        cout<<"No"<<endl;
        return;
   }
   s=' '+s;   
   if(n==4||s==" 1111")
   {
        cout<<"Yes"<<endl;
        return;
   }
   int num=sqrt(n);
   for(int i=num+1;i<=n-num;i++)
   {
        if((i%num==1||i%num==0)&&s[i]=='0') 
        {
            cout<<"No"<<endl;
            return;
        }
        if((i%num)!=1&&((i%num)!=0))
        {
            if(s[i]=='1')
            {
                cout<<"No"<<endl;
                return;
            }
        }
   }
   cout<<"Yes"<<endl;
}
signed main()
{
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

C. Longest Good Array

题目

Today, Sakurako was studying arrays. An array $a$ of length $n$ is considered good if and only if:

  • the array $a$ is increasing, meaning $a_{i - 1} < a_i$ for all $2 \le i \le n$;
  • the differences between adjacent elements are increasing, meaning $a_i - a_{i-1} < a_{i+1} - a_i$ for all $2 \le i < n$.

Sakurako has come up with boundaries $l$ and $r$ and wants to construct a good array of maximum length, where $l \le a_i \le r$ for all $a_i$.

Help Sakurako find the maximum length of a good array for the given $l$ and $r$.

实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e3;
const int M=2e5+10;
void solve()
{
   int n;
   cin>>n;
   for(int i=1;i<=n;i++)
   {
        int l,r;
        cin>>l>>r;
        int num=0;
        for(;num*(num+1)/2<=r-l;num++)
        {
            ;
        }
        if(num*(num+1)/2>r-l) num--;
        cout<<num+1<<endl;
   }
}
signed main()
{
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}

D. Sakurako’s Hobby

题目

For a certain permutation $p$$^{\text{∗}}$ Sakurako calls an integer $j$ reachable from an integer $i$ if it is possible to make $i$ equal to $j$ by assigning $i=p_i$ a certain number of times.

If $p=[3,5,6,1,2,4]$, then, for example, $4$ is reachable from $1$, because: $i=1$ $\rightarrow$ $i=p_1=3$ $\rightarrow$ $i=p_3=6$ $\rightarrow$ $i=p_6=4$. Now $i=4$, so $4$ is reachable from $1$.

Each number in the permutation is colored either black or white.

Sakurako defines the function $F(i)$ as the number of black integers that are reachable from $i$.

Sakurako is interested in $F(i)$ for each $1\le i\le n$, but calculating all values becomes very difficult, so she asks you, as her good friend, to compute this.

$^{\text{∗}}$A permutation of length $n$ is an array consisting of $n$ distinct integers from $1$ to $n$ in arbitrary order. For example, $[2,3,1,5,4]$ is a permutation, but $[1,2,2]$ is not a permutation (the number $2$ appears twice in the array), and $[1,3,4]$ is also not a permutation ($n=3$, but the array contains $4$).

实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
//const int M=2e5+10;
int dp[N];
int a[N],b[N];
int p[N];
int find(int x)
{
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
void solve()
{
   int n;
   cin>>n;
   for(int i=1;i<=n;i++)
   {
        cin>>a[i];
        p[i]=i;
   }
   string s;
   cin>>s;
   s=' '+s;
    for(int i=1;i<=n;i++)
    {
        p[find(a[i])]=find(i);
    }
    map<int,int>mp;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='0') mp[find(i)]++;
    }
    for(int i=1;i<=n;i++)
    {
        cout<<mp[find(i)]<<' ';
    }
    cout<<endl;
}
signed main()
{
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

E. Alternating String

题目

Sakurako really loves alternating strings. She calls a string $s$ of lowercase Latin letters an alternating string if characters in the even positions are the same, if characters in the odd positions are the same, and the length of the string is even.

For example, the strings ‘abab’ and ‘gg’ are alternating, while the strings ‘aba’ and ‘ggwp’ are not.

As a good friend, you decided to gift such a string, but you couldn’t find one. Luckily, you can perform two types of operations on the string:

  1. Choose an index $i$ and delete the $i$-th character from the string, which will reduce the length of the string by $1$. This type of operation can be performed no more than $1$ time;
  2. Choose an index $i$ and replace $s_i$ with any other letter.

Since you are in a hurry, you need to determine the minimum number of operations required to make the string an alternating one.

实现

考虑两种状态,一种n为偶数,一种为奇数,偶数必不进行删除操作,那只需要贪心选最小成本即可,奇数要枚举删除的位置,删完之后的位置奇偶的顺序会发生变化,因此记录一下i号位当前的各字母出现情况,注意区分奇偶序列,从1到n枚举,每次贪心选出最后剩什么字母的成本,取最小即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
//const int M=2e5+10;
int dp[N];
int a[N],b[N];
int ch1[N][27];
int ch2[N][27];
void solve()
{
    int n;
    cin>>n;
    string s;
    cin>>s;
    s=' '+s;
    map<char,int>mp1;
    map<char,int>mp2;
    if(n%2==0)
    {
        for(int i=1;i<=n;i++)
        {
            if(i%2==1) mp1[s[i]]++;
            else mp2[s[i]]++;
        }
        int ans1=0;
        int ans2=0;
        for(auto it:mp1) ans1=max(ans1,it.second);
        for(auto it:mp2) ans2=max(ans2,it.second);
        cout<<n-ans1-ans2<<endl;
    }
    else
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=26;j++)
            {
                ch1[i][j]=0;
                ch2[i][j]=0;
            }
            if(i%2==1)
            {
                ch1[i][s[i]-'a']++;
                for(int j=0;j<26;j++)
                {
                    ch1[i][j]+=ch1[i-1][j];
                    ch2[i][j]+=ch2[i-1][j];
                }
            }
            else
            {
                ch2[i][s[i]-'a']++;
                for(int j=0;j<26;j++)
                {
                    ch1[i][j]+=ch1[i-1][j];
                    ch2[i][j]+=ch2[i-1][j];
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int max1=0;
            int max2=0;
            for(int j=0;j<26;j++)
            {
                max1=max(ch2[n][j]-ch2[i][j]+ch1[i-1][j],max1);
                max2=max(ch1[n][j]-ch1[i][j]+ch2[i-1][j],max2);
            }
            ans=max(ans,max1+max2);
        }
        cout<<n-ans<<endl;
    }
}
signed main()
{
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

F. Sakurako’s Box

题目

Sakurako has a box with $n$ balls. Each ball has it’s value. She wants to bet with her friend that if the friend randomly picks two balls from the box (it could be two distinct balls, but they may have the same value), the product of their values will be the same as the number that Sakurako guessed.

Since Sakurako has a PhD in probability, she knows that the best number to pick is the expected value, but she forgot how to calculate it. Help Sakurako and find the expected value of the product of two elements from the array.

It can be shown that the expected value has the form $\frac{P}{Q}$, where $P$ and $Q$ are non-negative integers, and $Q \ne 0$. Report the value of $P \cdot Q^{-1}(\bmod 10^9+7)$.

实现

我恨取模

image-20240903002706846

算贡献+组合数+逆元

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int dp[N];
int a[N],b[N];
const int mod=1e9+7; 
int quick_pow(int a,int b)
{
    int ans=1;
    while(b){
        if(b&1) ans=(ans*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return ans;
}
int inv(int a,int b)
{
    return (a*quick_pow(b,mod-2))%mod;
}
void solve()
{
    int n;
    cin>>n;
    int sum=0;
    for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i],sum%=mod;
    int num=(n-1)*n/2;
    num%=mod;
    int d1=0;
    for(int i=1;i<=n;i++)
    {
        sum-=a[i];
        d1+=(a[i]%mod)*((sum+mod)%mod);
        d1%=mod;
    }
    int ans=inv(d1,num);
    cout<<(ans+mod)%mod<<endl;
}
signed main()
{
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

G. Sakurako’s Task

题目

Sakurako has prepared a task for you:

She gives you an array of $n$ integers and allows you to choose $i$ and $j$ such that $i \neq j$ and $a_i \ge a_j$, and then assign $a_i = a_i - a_j$ or $a_i = a_i + a_j$. You can perform this operation any number of times for any $i$ and $j$, as long as they satisfy the conditions.

Sakurako asks you what is the maximum possible value of $mex_k$$^{\text{∗}}$ of the array after any number of operations.

$^{\text{∗}}$$mex_k$ is the $k$-th non-negative integer that is absent in the array. For example, $mex_1({1,2,3 })=0$, since $0$ is the first element that is not in the array, and $mex_2({0,2,4 })=3$, since $3$ is the second element that is not in the array.

实现

尽可能让所有的数字变小就是最优解,手动模拟一下会发现最后的数组排列为i*数组最大公因数(0<=i<=n)

将k按顺序插入即是最答案

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
const int mod=1e9+7; 
int a[N];
int gcd(int a,int b)
{
    if(a%b==0) return b;
    else return gcd(b,a%b);
}
void solve()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int num=0;
    for(int i=1;i<=n;i++)
    {
        if(!num) num=a[i];
        else num=gcd(num,a[i]);
    }
    if(n == 1)
    {
       if(k>a[1]) cout<<k<<endl;
       else cout<<k-1<<endl;
    }
    else
    {
        if(num==1) cout<<n-1+k<<endl;
        else
        {
            int sum=((k+num-2)/(num-1));
            sum=min(sum,n);
            cout<<k+sum-1<<endl;
        }
    }
}
signed main()
{
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}
阅读全文

dijkstra求最短路(多源版本)

算法 2024/9/1
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e3;
int u[N],v[N];
int dist[N][N];
vector<int>e[N];
bool st[N][N];
typedef pair<int,int> PII;
void dijkstra(int root)
{
    priority_queue<PII, vector<PII>, greater<PII>>heap;
    dist[root][root]=0;
    heap.push({0,root});
    while(heap.size())
    {
        auto k=heap.top();
        heap.pop();
        int ver=k.second;
        int distence=k.first;
        if(st[root][ver]) continue;
        st[root][ver]=1;
        for(int i=0;i<e[ver].size();i++)
        {
            if(dist[root][e[ver][i]]>=distence+dist[ver][e[ver][i]])
            {
                dist[root][e[ver][i]]=distence+dist[ver][e[ver][i]];
                heap.push({dist[root][e[ver][i]],e[ver][i]});
            }
        }
    }
}
void solve()
{
    int n,m;
    cin>>n>>m;
    memset(dist,127,sizeof(dist));
    for(int i=1;i<=m;i++)
    {
        int w;
        cin>>u[i]>>v[i]>>w;
        if(!st[u[i]][v[i]])
        {
            st[u[i]][v[i]]=1;
            st[v[i]][u[i]]=1;
            e[u[i]].push_back(v[i]);
            e[v[i]].push_back(u[i]);
        }
        dist[u[i]][v[i]]=min(dist[u[i]][v[i]],w);
        dist[v[i]][u[i]]=min(dist[v[i]][u[i]],w);
    }
    memset(st,0,sizeof(st));
    for(int i=1;i<=n;i++)
    {
        dijkstra(i);
    }
}
signed main()
{
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}
阅读全文

AtCoder Beginner Contest 369

题解 2024/8/31

A - 369

问题陈述

给你两个整数 $A$ 和 $B$ 。

有多少个整数 $x$ 满足以下条件?

  • 条件:可以将三个整数 $A$ 、 $B$ 和 $x$ 按一定顺序排列,组成一个算术序列。

当且仅当 $q-p$ 等于 $r-q$ 时,三个整数 $p$ , $q$ 和 $r$ 按此顺序排列的序列是算术序列。

实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5;
void solve()
{
   int a,b;
   cin>>a>>b;
   if(a==b)
   {
         cout<<1<<endl;
         return ;
   }
   if(abs(b-a)%2==0) cout<<3<<endl;
   else cout<<2<<endl;
}
signed main()
{
    int t=1;
    while(t--)
    {
        solve();
    }
}

B - Piano 3

问题陈述

高桥有一架钢琴,上面有 $100$ 个排成一行的琴键。从左边开始的第 $i$ 个键叫做 $i$ 键。

他要逐个按下 $N$ 个键来演奏音乐。在按下 $i$ /th键时,他将用左手按下 $A_i$ 键,如果是 $S_i=$ ,则用右手按下 $A_i$ 键。如果按 $S_i=$ 则用左手,如果按 $S_i=$ 则用右手。R.

开始演奏前,他可以将双手放在任意键上,此时他的疲劳度为 0。在演奏过程中,如果他将一只手从键 $x$ 移动到键 $y$ ,疲劳度会增加 $|y-x|$ (反之,除移动双手外,疲劳度不会增加)。用手按下某个键时,该手必须放在该键上。

找出表演结束时可能的最低疲劳度。

实现

简单模拟即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5;
void solve()
{
   int n;
   cin>>n;
   int l=0;
   int r=0;
   int ans=0;
   for(int i=1;i<=n;i++)
   {
        int x;
        char ch;
        cin>>x>>ch;
        if(ch=='L') 
        {
            if(l==0) l=x;
            else ans+=(abs(l-x)),l=x;
        }
        else
        {
            if(r==0) r=x;
            else ans+=(abs(r-x)),r=x;
        }
   }
   cout<<ans<<endl;
}
signed main()
{
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}

C - Count Arithmetic Subarrays

问题陈述

给你一个由 $N$ 个正整数 $A=(A_1,A_2,\dots,A_N)$ 组成的序列。

求满足 $1\leq l\leq r\leq N$ 的一对整数 $(l,r)$ 中,子序列 $(A_l,A_{l+1},\dots,A_r)$ 构成算术级数的个数。

当且仅当存在一个 $d$ 使得 $x_{i+1}-x_i=d\ (1\leq i < |x|)$ 是算术级数时,序列 $(x_1,x_2,\dots,x_{|x|})$ 才是算术级数。特别地,长度为 $1$ 的序列总是算术级数。

实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5;
int a[N];
int b[N];
void solve()
{
   int n;
   cin>>n;
   for(int i=1;i<=n;i++) cin>>a[i];
   for(int i=1;i<n;i++)
   {
        b[i]=(a[i+1]-a[i]);
   }
   int r=1;
   int ans=n;
   for(int l=1;l<n;l++)
   {
        while(b[r+1]==b[l]&&r+1<n) r++;
        int num=r-l+1;
        //cout<<num<<' ';
        ans+=(num)*(num+1)/2;
        l=r;
   }
   cout<<ans<<endl;
}
signed main()
{
    int t=1;
    while(t--)
    {
        solve();
    }
}

D - Bonus EXP

问题陈述

高桥将依次遇到 $N$ 只怪物。 $i$ 个怪物 $(1\leq i\leq N)$ 的力量为 $A _ i$ 。

对于每只怪物,他都可以选择放走或打败它。
每次行动都会获得以下经验值:

  • 如果放走怪物,他将获得 $0$ 点经验值。
  • 如果他以 $X$ 的力量击败了怪物,则会获得 $X$ 点经验值。
    如果击败的是偶数怪物(第 2 个、第 4 个……),他将额外获得 $X$ 点经验值。

求他能从 $N$ 个怪物身上获得的经验值上限。

实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5;
int a[N];
int b[N];
int dp[N][2][2];
void solve()
{
   int n;
   cin>>n;
   for(int i=1;i<=n;i++) cin>>a[i];
   for(int i=1;i<=n;i++)
   {
        dp[i][0][1]=max(dp[i-1][0][1],dp[i-1][1][1]);
        dp[i][0][0]=max(dp[i-1][0][0],dp[i-1][1][0]);
        dp[i][1][1]=max(dp[i-1][1][0],dp[i-1][0][0])+a[i];
        if(i==1) continue;
        dp[i][1][0]=max(dp[i-1][1][1],dp[i-1][0][1])+2*a[i];
   }
   cout<<max(dp[n][1][0],dp[n][1][1])<<endl;
}
signed main()
{
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}

E - Sightseeing Tour

问题陈述

有 $N$ 个岛屿和 $M$ 座双向桥梁连接两个岛屿。这些岛屿和桥梁的编号分别为 $1$ 、 $2$ 、 $\ldots$ 、 $N$ 和 $1$ 、 $2$ 、 $\ldots$ 、 $M$ 。
大桥 $i$ 连接着岛屿 $U_i$ 和 $V_i$ ,从任一方向穿过大桥所需的时间为 $T_i$ 。
没有一座桥将一个岛屿与它自己连接起来,但是有可能两座岛屿被不止一座桥直接连接起来。
人们可以通过一些桥梁来往于任意两个岛屿之间。

给你 $Q$ 个问题,请逐一回答。 $i$ -th 查询如下:

给出了 $K_i$ 个不同的桥:桥 $B_{i,1}, B_{i,2}, \ldots, B_{i,K_i}$ 。
求从岛屿 $1$ 到岛屿 $N$ 所需的最少时间,每座桥梁至少使用一次。
只考虑过桥的时间。
你可以以任何顺序和方向通过给定的桥梁。

实现

​ 求n遍dijkstral算出各点间的最短路,接着通过全排列枚举必走k个不同桥的走法,要注意不止枚举桥的顺序,还要枚举从u到v还是从v到u,每架桥对应两种状态,因此用01表示,则共2的k次方种选法。

​ dist[i] [j]表示从上一次走的桥的出口在i,要走到这一次桥的入口j,当选择的是第一架桥时,从1号点出发,到达第x=1架桥的入口,下次循x=2时则要选择从x-1出发,走到x,表示为dist[b[x-1]] [b[x]],所以最后一架桥作为出口时,此时循环了x=k+1次,表示为dist[b[k]] [n]到达n号点

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e3;
const int M=2e5+10;
int u[M],v[M],w[M];
int dist[N][N];
vector<int>e[M];
bool st[N][N];
int b[M];
typedef pair<int,int> PII;

void dijkstra(int root)
{
    priority_queue<PII, vector<PII>, greater<PII>>heap;
    dist[root][root]=0;
    heap.push({0,root});
    while(heap.size())
    {
        auto k=heap.top();
        heap.pop();
        int ver=k.second;
        int distence=k.first;
        if(st[root][ver]) continue;
        st[root][ver]=1;
        for(int i=0;i<e[ver].size();i++)
        {
            if(dist[root][e[ver][i]]>=distence+dist[ver][e[ver][i]])
            {
                dist[root][e[ver][i]]=distence+dist[ver][e[ver][i]];
                heap.push({dist[root][e[ver][i]],e[ver][i]});
            }
        }
    }
}
void solve()
{
    int n,m;
    cin>>n>>m;
    memset(dist,127,sizeof(dist));
    for(int i=1;i<=m;i++)
    {
        cin>>u[i]>>v[i]>>w[i];
        if(!st[u[i]][v[i]])
        {
            st[u[i]][v[i]]=1;
            st[v[i]][u[i]]=1;
            e[u[i]].push_back(v[i]);
            e[v[i]].push_back(u[i]);
        }
        dist[u[i]][v[i]]=min(dist[u[i]][v[i]],w[i]);
        dist[v[i]][u[i]]=min(dist[v[i]][u[i]],w[i]);
    }
    memset(st,0,sizeof(st));
    for(int i=1;i<=n;i++)
    {
        dijkstra(i);
    }
    int q;
    cin>>q;
    while(q--)
    {
        int k;
        cin>>k;
        for(int i=1;i<=k;i++) cin>>b[i];
        sort(b+1,b+1+k);
        int ans=1e12;
        do
        {
            for(int j=0;j<1<<k;j++)
            {
                int cur=0;
                for(int i=1;i<=k;i++)cur+=w[b[i]];
                for(int i=1;i<=k+1;i++)cur+=dist[i==1?1:(j>>i-2)&1?v[b[i-1]]:u[b[i-1]]][i>k?n:(j>>i-1)&1?u[b[i]]:v[b[i]]];
                ans=min(ans,cur);
            }
        } while (next_permutation(b+1,b+1+k));
        cout<<ans<<endl;
    }   
}
signed main()
{
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}
阅读全文

codeforces第一个4000分!

杂谈 2024/8/31

见证历史,codeforces上第一个红黑名——tourist

image-20240831112043330

阅读全文

图床搭建

杂谈 2024/8/30

在搭建好博客之后,这时写博客想要实现插入图片的功能还需要一些操作,以下为使用腾讯cos及picgo软件实现图床搭建的教程

一.购买腾讯对象存储

图床的搭建方案还是很多的,比如Github仓库 + Picgo ,giteec仓库 + Picgo,但考虑到稳定性和高效性,便宜量大的云储存也是不错的选择,其中我购买的是[腾讯对象存储](对象存储数据处理_COS数据处理_数据处理方案-腾讯云 (tencent.com))

image-20240830212717098

按照需求购买之后进入控制台,点击创建存储桶

image-20240830212942566

这里一定要选择公有读私有写

之后按照提示创建即可,创建完成后进入存储桶,创建文件夹,(例如img)记住该文件夹的地址,之后要用到

image-20240830213219242

二.下载Picgo软件

下载地址很多,这里就不提供了,下载完成后进入图床设置

image-20240830213548018

按照提示填入之后,点击设为默认图床即可完成。

[!NOTE]

Secretld,SecretKey均在腾讯云密钥管理中获取

Bucket 即为创建存储桶的名称

三.设置你的md编辑器

这里以typor为例,进入图像相关设置,勾选上传服务为 Picgo(app),设置正确路径即可

image-20240830213912270

之后在插入图片的同时点击上传图片就会自动上传至腾讯云储存中了

阅读全文
1 ... 3
avatar
joso

齐鲁工业大学(山东省科学院)