打完十场回顾一下之前一些的题 都是简单题 难的我不会

继续努力  

Luxury cruise ship

纯签到 完全背包。数据有点大。三个物品价值是互质的,我们把7,31,365乘起来,用n%(7*31*365),计算dp[n]+n/(7*31*365)*31*365即可

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 365 * 31 * 7+1;

int dp[N], w[4] = { 0,7,31,365 };
int n;


signed main() {
    ios::sync_with_stdio(false);

    fill(dp, dp + 365 * 31 * 7+1, 0x3f3f3f3f);
    dp[0] = 0;
    for (int i = 1; i <= 3; i++) 
    {
        for (int j = w[i]; j <= N; j++) 
            dp[j] = min(dp[j], dp[j - w[i]] + 1);
    }
    int t;
    cin >> t;
    while (t--) 
    {
        cin >> n;
        int t = n % (365 * 31 * 7);
        if (dp[t] == 0x3f3f3f3f)
            cout << -1 << endl;
        else
            cout << dp[t] + n / (365 * 31 * 7) * 31 * 7 << endl;
    }
}

 

Package Delivery

贪心 堆优化

当一个快递到达截至时间时,可取快递小于等于k个,那我们直接全部取出即可。大于k个,那么我们取出最紧急(就是r最小)的k个。

对l,r都有一个贪心的过程,先对l再对r。

#include<bits/stdc++.h>
using namespace std;

const int N=400010;
typedef pair<int,int> PII;

int l[N],r[N];
struct node{
    int l,r;
}p[N];

bool cmp(node a,node b)
{
    return a.l<b.l;
}

void solve()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&p[i].l,&p[i].r);
    sort(p+1,p+n+1,cmp);
    priority_queue<PII,vector<PII>,greater<PII> >q;
    while(!q.empty()) q.pop();
    q.push({p[1].r,p[1].l});
    int t=p[1].r,ans=0;
    for(int i=2;i<=n;)
    {
        while(i<=n&&(p[i].l<=t||t==-1))
        {
            if(t==-1) t=p[i].r;
            t=min(t,p[i].r);
            q.push({p[i].r,p[i].l});
            i++;
        }
        if(!q.empty())
        {
            ans++;
            if(q.size()<=k){
                while(!q.empty())    
                    q.pop();
                t=-1;
            }
            else{
                int tt=k;
                while(tt--)      
                    q.pop();
                t=q.top().first;
            }
        }
    }
    ans+=(q.size()+k-1)/k;
    printf("%d\n",ans);    
}

signed main()
{
    int _;
    cin>>_;
    while(_--) {
        solve();
    }
}

 

Climb Stairs 

这个题数据其实比较水非常水  官方题解是线段树 其实以这个题的数据之弱  直接暴力枚举加一个前缀和判断来剪枝就能过  全场都过直接做成签到题~

容易看出贪心做法(证明略)  就是往回跳的过程的判断 不能暴力枚举 线段树来维护优化能做(O(nlogn))   用dp的思想也能维护出 而且更快(O(n))   暴力加简单的剪枝也能过.......

随便搞的暴力+剪枝code(再吐槽一下数据真的拉):

#include<bits/stdc++.h>
#define int long long
using namespace std;


int read(int &n){
    char ch=' '; int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar())q=q*10+ch-48;
    n=q*w; return n;
}

const int N=1e5+10;
int n,k,a[N];
int f[N]; 

void sovle()
{
    read(n); read(a[0]); read(k); 
        
    f[0]=a[0]; 
    for(int i=1;i<=n;i++){
        read(a[i]);
        f[i]=f[i-1]+a[i];
    }
        
    int F=1; 
        
    int sum=a[0];
    for(int i=1;i<=n;i++){ 
        
            
        if(sum>=a[i]){ 
            sum+=a[i];
        } 
        else{ 
            int F2=0;
            int len1=-1;
                
            if(k>=n-i+1){ 
                k=n-i+1;
            }
                    
            for(int j=2;j<=k;j++){ 
                int cnt=sum;
                if(cnt+f[i+j-1]-f[i] < a[i]){ 
                    continue; 
                }
                    
                F2=1; 
                len1=j; 
                    
                for(int k0=i+j-1;k0>=i;k0--){
                    if(cnt>=a[k0]){
                        cnt+=a[k0];
                    }
                    else{ 
                        F2=0;
                        break;
                    }
                }
                if(F2)break;
            } 
                
            if(F2){
                sum += f[i+len1-1]-f[i-1]; 
                i += len1-1; 
            } 
            else{
                F=0;
                break;
            }
        }
    }
        
    if(F)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}

signed main(){ 
    int t; 
    read(t); 
    while(t--){
        sovle();
    }
}

 

Planar graph

是一个删边的题目,删完之后是一个没有环的最大连通子图,没错这就是。求删边,我们反过来需要留下的边构成最小生成树。那么不留下的就是要删的边了,由于要删字典序最小,我们从字典序更大的开始添加边。

#include<bits/stdc++.h>
using namespace std;

const int N=2e6+10;

int f[N],u[N],v[N];
stack<int>st;
int n,m;

int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}

void sovle()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    scanf("%d%d",&u[i],&v[i]);
    for(int i=m;i>=1;i--)
    {
        int fx=find(u[i]),fy=find(v[i]);
        if(fx==fy)
            st.push(i);
        else 
            f[fx]=fy;
    }
    printf("%d\n",st.size());
    while(!st.empty())
    {
        printf("%d ",st.top());
        st.pop();
    }
    puts("");
}

signed main()
{
    int _;
    cin>>_;
    while(_--)
    {
        sovle();
    }
}

 

Link is as bear

求操作过后的最大值,其实等价于求取x个数,x<=n,使得异或和最大,就是一个线性基的常规用法。

此题卡常,不要用c++输入输出 ,用快读或c的输入输出都可。

 

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e5+10;

int n;
int d[110],a[N];

void add(int x)
{
    for(int i=60;i>=0;i--)
    {
        if(x&(1ll<<i))
        {
            if(d[i])
            x^=d[i];
            else
            {
                d[i]=x;
                break;
            }
        }
    } 
}

void sovle()
{
    scanf("%d",&n);
    memset(d,0,sizeof d);    
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        add(a[i]);
    }
    int ans=0;
    for(int i=60;i>=0;i--)
    if((ans^d[i])>ans)
    ans=ans^d[i];
    printf("%lld\n",ans);
}

signed main()
{
    int _;
    cin>>_;
    while(_--)
    {
        sovle();
    }    
} 

 

 Even Tree Split

签到dfs ,题意是把树分割成偶数节点的集合,从根跑一遍dfs回溯的时候数组记录每个节点的子树节点数+1(加1是自身也算),是偶数满足分割的条件,最后组合起来就是2^cnt-1。(组合数学 集合论)

此题卡常,用vector会被卡,输入输出不要用c++,时间复杂度快到极限时(10^8级别),就不要用一些效率低的写法了。 

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e5+5,mod=998244353;
int h[N],e[2*N],ne[2*N],idx;
int n;
int c[N];

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
void add(int a,int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
void init() { for(int i=0;i<N;i++) c[i] = 1; n = read(); int u,v; for(int i=1;i<=n-1;i++){ u = read(), v = read(); add(u,v), add(v,u); } } int pow_mod(int a, int n, int m) { long long ans = 1; while(n){ if(n&1){ ans = (ans * a) % m; } a = (a * a) % m; n >>= 1; } return ans; } void dfs(int x,int fa) { // for(auto y:g[x]){ // if(y==fa) // continue; // dfs(y,x); // c[x]+=c[y]; // } for(int i = h[x]; ~i; i = ne[i]) { int j = e[i]; if(j == fa) continue; dfs(j,x); c[x] += c[j]; } } void sovle() { int cnt=0; for(int i=2;i<=n;i++){ if(c[i]%2==0){ cnt++; } } printf("%lld\n",pow_mod(2,cnt,mod)-1); } signed main() { int _; _ = read(); while(_--){ memset(h, -1, sizeof h); idx = 0; init(); if(n<4){ printf("0\n"); continue; } dfs(1,0); sovle(); } }

 

(努力更新中 这几天能写的会全部补完)

除了一些不想补的 和对我来说太难的

 

posted on 2022-08-21 17:56  unique_pan  阅读(148)  评论(0编辑  收藏  举报