B2. Books Exchange (hard version)

题目说,输入的是一个排列,那么每个数(1~n)都会出现,那么每个数都会出现在一个简单环中,bfs处理一下这些点在所在环的数量即可。。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
vector<int>G[N];
int n,b[N];
int a[N],ans[N];
int tot;
int bfs(int uu,int tot)
{
    queue<int>que;
    que.push(uu);
    int ans=0;
    while(que.size()){
        int u=que.front();que.pop();
        //printf("u:%d\n");
        if(b[u]) continue;
        b[u]=tot;ans++;
        for(int v:G[u]){
                //printf("v:%d\n",v);
            que.push(v);
        }
    }
    //printf("ans:%d\n",ans);
    return ans;
}
int main()
{
	int _;cin>>_;while(_--)
	{
	    scanf("%d",&n);
	    for(int i=1;i<=n;++i) G[i].clear(),b[i]=0;
	    tot=0;
 
	    for(int i=1;i<=n;++i) {
 
            scanf("%d",&a[i]);
            G[i].push_back(a[i]);
	    }
	    for(int i=1;i<=n;++i)
        {
            if(b[i]==0){
                tot++;
                ans[tot]=bfs(i,tot);
            }
        }
        for(int i=1;i<=n;++i){
            printf("%d ",ans[b[i]]);
        }
        puts("");
	}
}

C2. Good Numbers (hard version)

因为是3的某次方相加,那么看作3进制下,每位下就是0或者1,那么我就将输入的x求3进制下的长度,用ans每一位都是1,再高位一个一个减去当前的1,是否大于等于即可

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
const int N=1e4+10;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
ll cal(ll x)
{
    ll t=x;
    ll tmp=0;
    ll p=0;
    while(t){
        ll d=x%3;
        t=t/3;
        tmp+=pow(3ll,p);
        ++p;
    }
    tmp+=pow(3ll,p);
    //printf("tmp:%lld\n",tmp);
    for(ll i=p;i>=0;--i)
    {
        ll t1=pow(3ll,i);
        if(tmp-t1>=x) tmp-=t1;
    }
 
    return tmp;
}
int main()
{
	int _;cin>>_;while(_--)
	{
	    ll x;
	    scanf("%lld",&x);
	    ll ans=cal(x);
	    printf("%lld\n",ans);
	}
}

D2. Too Many Segments (hard version)

每个位置下去掉右端点最远的即可:结合差分弄一下就可以了。。。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,k;
struct node
{
  int l,r,id;
  bool operator <(const node &o) const
  {
      return o.r>r;
  }
};
vector<node>G[N];
vector<int>ans;
int vis[N];
int main()
{
    scanf("%d%d",&n,&k);
    int mx=0;
    for(int i=1;i<=n;++i)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        mx=max(mx,r);
        vis[l]++;
        vis[r+1]--;
        G[l].push_back({l,r,i});
    }
 
    int sum=0;
    priority_queue<node>que;
    for(int i=1;i<=mx;++i)
    {
        sum+=vis[i];
        for(auto v:G[i]) que.push(v);
 
        while(sum>k)
        {
            node now=que.top();que.pop();
            ans.push_back(now.id);
            vis[now.r+1]++;
            sum--;
        }
    }
    printf("%d\n",ans.size());
    for(int v:ans) printf("%d ",v);
 
}

E. By Elevator or Stairs?

设dp[i][0]为从1开始走楼梯来到i层,dp[i][1]为从1开始做电梯来到i层

显然易见dp方程:

dp[i][0]=min(dp[i-1][0]+a[i],dp[i][0]);
dp[i][0]=min(dp[i-1][1]+a[i],dp[i][0]);
dp[i][1]=min(dp[i-1][0]+c+b[i],dp[i][1]);
dp[i][1]=min(dp[i-1][1]+b[i],dp[i][1]);
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
ll a[N],b[N];
ll dp[N][2];
int main()
{
    memset(dp,inf,sizeof(dp));
    int n,c;
    cin>>n>>c;
    for(int i=2;i<=n;++i){
        scanf("%lld",&a[i]);
    }
    for(int i=2;i<=n;++i){
        scanf("%lld",&b[i]);
    }
    dp[1][0]=0;
    dp[1][1]=c;
    for(int i=2;i<=n;++i){
        dp[i][0]=min(dp[i-1][0]+a[i],dp[i][0]);
        dp[i][0]=min(dp[i-1][1]+a[i],dp[i][0]);
        dp[i][1]=min(dp[i-1][0]+c+b[i],dp[i][1]);
        dp[i][1]=min(dp[i-1][1]+b[i],dp[i][1]);
 
    }
    for(int i=1;i<=n;++i) printf("%lld ",min(dp[i][0],dp[i][1]));
 
}