-TEST 19 for NOIP 。。。(105-300)

头更更更大

这个11月完就要去搞NOIP了。。。

11月10天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。


emmm。。。。。又是三题全炸。。。
第一题做过忘了,顺手摔了一个优先队列上去,85。后来发现两个队列就能解决。。
第二题桶排序,搞了一个半小时心态爆炸放弃了去搞T3,回来顺手乱打了个暴力,20。
第三题最小生成树,暴力跑,但是由于没有开long long爆零。。。否则30到手。。。

按理说205很轻松的。。。orz

下面面详细解答:

T1(85/100):Blash数集

problem

题意:一个数集,规定如果x在集合中,那么 2x+1,3x+1 也在集合中。现在给你初始值x,询问第n大的数是多少。
样例

  • 输入
    1 100
    28 5437

  • 输出
    418
    900585

solution

当时知道是原题但是就是想不起来了。。。orz然后甩了个优先队列上去。
正解是用两个数组分别存储2x+1的项与3x+1的项,然后去去重就完事了。

T2(20/100):序列操作

problem

题意:给你一个数列,接下来要进行m次操作,每次操作要求你把数组中的c个正整数-1,问你最多能进行几次操作。
样例

  • 输入
    3 5
    1 2 5
    1 2 3 2 1

  • 输出
    3

solution

正解是二分,然而因为元素最大值不过1e4所以桶排序貌似跑的也不慢。。这里讲桶排序的。
相当于每次操作暴力模拟,如果桶中的元素少于要找的数,就把整个桶排序中的元素向下移一层(先把下面那层处理了再移);如果不少那就把需要找的数向下移一层就行。
论代码风格的简洁性的重要性。。。稍微改了下就是100。。。

T3(0/100):图

problem

题意
一个无向图,其中A条边的权值为k+x(每条边的权值由定值k与全局变量v决定),B条边的权值为k-x,而且这A,B条边分别能使整个图联通。询问对于不同的v,这个图的最小生成树的边权和是多少。
样例

  • 输入 
    5 4 4 4
    1 3 2
    1 2 0
    3 5 5
    3 4 10
    5 4 7
    2 3 6
    1 2 1000
    3 4 1000
    0
    1
    2
    3

  • 输出
    14
    16
    18
    18

solution

30%随便乱搞,暴力Kruskal。
50%利用特殊数据,A边一定是最优的,直接按着A边建就行。
100%。。。还是自己去后面看DZY大佬的代码吧orz

感想

审题!!!多打暴力!!!沉住气!!!多练模板!!!

代码:

T1:

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

#define U_MAX 200
inline char *get_str(char *str)
{
    fgets(str,U_MAX,stdin);
    if(str[strlen(str)-1] == '\n')
        str[strlen(str)-1] = '\0';
    return str;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=4000000;
int top1,que1[kkk];
int top2,que2[kkk];
int a,n,m;
int main()
{
    //freopen("blash.in","r",stdin);
    //freopen("blash.out","w",stdout);  
    while(~scanf("%d%d",&a,&n))
    {
        int cnt1=1,cnt2=1;
        if(n==1){cout<<a<<endl;continue;}
        que1[top1=1]=2*a+1;
        que2[top2=1]=3*a+1;
        n-=1;
        while(n--)
        {
            if(que1[cnt1]==que2[cnt2])
            {
                a=que1[cnt1];
                que1[cnt1]=0;cnt1++;
                que2[cnt2]=0;cnt2++;
            }
            else if(que1[cnt1]<que2[cnt2])
            {
                a=que1[cnt1];
                que1[cnt1]=0;cnt1++;
            }
            else if(que1[cnt1]>que2[cnt2])
            {
                a=que2[cnt2];
                que2[cnt2]=0;cnt2++;
            }
            que1[++top1]=2*a+1;que2[++top2]=3*a+1;
        }
        cout<<a<<endl;
    }
}

T2

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=10005;

int n,m,flag;
int h,s[kkk];
int sum[kkk];

int main()
{
    //freopen("sequence.in","r",stdin);
    //freopen("sequence.out","w",stdout);   
    n=read();   m=read();   flag=1;
    for(int i=1;i<=n;i++)h=read(),sum[h]++,sum[0]=max(sum[0],h);
    h=sum[0];
    for(int i=1;i<=m;i++)
    {
        n=read();
        int tot=0,pos=0;
        for(int j=h;j>=1;j--)
        {
            if(tot+sum[j]>=n)
                {pos=j+1;break;}
            tot+=sum[j];
        }
        if(pos==0){cout<<i-1;return 0;}

        int tmp=n-tot;
        sum[pos-1]-=tmp;
        sum[pos-2]+=tmp;

        for(int j=pos;j<=h;j++)
        {
            sum[j-1]+=sum[j];
            sum[j]=0;
        }
    }
    cout<<m<<endl;
}

T3

std_50%.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

#define U_MAX 200
inline char *get_str(char *str)
{
    fgets(str,U_MAX,stdin);
    if(str[strlen(str)-1] == '\n')
        str[strlen(str)-1] = '\0';
    return str;
}

inline void write(int x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}

const int kkk=100005;
struct node{
    int u,v,k,flag;
}side[4*kkk];

int fa[kkk];
inline int ga(int x){return ((fa[x]==x)?(x):(fa[x]=ga(fa[x])));}

int v;
bool compi(const node&a,const node&b){return (a.k+a.flag*v)<(b.k+b.flag*v);}
bool comp(const node&a,const node&b){return (a.k)<(b.k);}

int n,a,b,q,ans1,ans2,cnt1,cnt2;
ll get_ans1()
{
    ll ans=0;
    for(int i=1;i<=n;i++)fa[i]=i;
    sort(side+1,side+a+b+1,compi);
    for(int i=1;i<=a+b;i++)
    {
        int u=side[i].u;
        int g=side[i].v;
        if(ga(u)!=ga(g))
        {
            fa[ga(u)]=ga(g);
            ans+=1LL*(side[i].k+side[i].flag*v);
        }
    }
    return ans;
}   

int main()
{
    //freopen("mst.in","r",stdin);
    //freopen("mst.out","w",stdout);    
    n=read();a=read();b=read();q=read();int flag=0;
    for(int i=1;i<=a;i++)
    {
        side[i].u=read();
        side[i].v=read();       
        side[i].k=read();   
        side[i].flag=1;
        if(side[i].k>1e8)flag=1;
    }
    for(int i=1;i<=b;i++)
    {
        side[i+a].u=read();
        side[i+a].v=read();     
        side[i+a].k=read();
        side[i+a].flag=-1;  
        if(side[i+a].k<9*1e8||side[i+a].k>1e9)flag=1;       
    }   
    if(flag)
    for(int i=1;i<=q;i++)
    {
        v=read();
        cout<<get_ans1()<<endl;
    }
    else
    {
        int numy=0;
        ll ans=0;
        for(int i=1;i<=n;i++)fa[i]=i;
        sort(side+1,side+a+1,comp);
        for(int i=1;i<=a;i++)
        {
            int u=side[i].u;
            int g=side[i].v;
            if(ga(u)!=ga(g))
            {
                fa[ga(u)]=ga(g);
                ans+=1LL*(side[i].k);
                numy++;
            }
        }
        for(int i=1;i<=q;i++)
        {
            v=read();
            cout<<ans+1LL*numy*v<<endl;
        }
    }
}

std.cpp

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();int i=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
    return i*f;
}
inline void W(long long x){
    static int buf[50];
    if(!x){putchar('0');return;}
    if(x<0){putchar('-');x=-x;}
    while(x){buf[++buf[0]]=x%10;x/=10;}
    while(buf[0])putchar(buf[buf[0]--]+'0');
}
const int Maxn=1e5+50; 
const int INF=0x3f3f3f3f;
int n,Acnt,Bcnt,q,anc[Maxn];
long long ans[Maxn],sum;
struct node{
    node *lc,*rc,*fa,*mxid;
    int val,mx,x,y,revtag;
    inline void rev(){
        revtag^=1;
        swap(lc,rc);
    }
    inline void pushdown(){
        if(!revtag)return;
        if(lc)lc->rev();
        if(rc)rc->rev();
        revtag^=1;
    }
    inline void upt(){
        mxid=this;mx=val;
        if(lc&&lc->mx>mx)mxid=lc->mxid,mx=lc->mx;
        if(rc&&rc->mx>mx)mxid=rc->mxid,mx=rc->mx;
    }
}Pool[Maxn<<2],*pool=Pool,*pos[Maxn];
inline node* newnode(int v,int x,int y){
    ++pool;
    pool->lc=NULL;pool->rc=NULL;pool->fa=NULL;
    pool->val=v;pool->mx=v;pool->mxid=pool;
    pool->x=x;pool->y=y;
    return pool;
}
struct E{
    int x,y,w;
    friend inline bool operator <(const E &a,const E &b){
        return a.w<b.w;
    } 
}A[Maxn<<1],B[Maxn<<1];
struct E2{
    int x,y,w,low,rpc;
    inline bool operator =(const E &b){
        x=b.x,y=b.y,w=b.w;
    }
}Bnow[Maxn];
struct Q{
    int v,id;
}qry[Maxn];
inline bool cmpv(const Q &a,const Q &b){return a.v<b.v;}
inline bool cmpw(const E2 &a,const E2 &b){return a.w<b.w;}
inline bool cmplow(const E2 &a,const E2 &b){return a.low<b.low;}
inline int getanc(int x){return (anc[x]==x)?(x):(anc[x]=getanc(anc[x]));}
inline bool isroot(node *x){
    return !x->fa||(x->fa->lc!=x&&x->fa->rc!=x);
}
inline bool which(node *x){
    return x->fa->lc==x;
}
inline void rotate(node *x){
    node *y=x->fa,*z=y->fa;
    if(!isroot(y))(z->lc==y?z->lc:z->rc)=x;
    x->fa=z;y->fa=x;
    if(y->lc==x){
        node *b=x->rc;
        x->rc=y;
        y->lc=b;
        if(b)b->fa=y;
    }else{
        node *b=x->lc;
        x->lc=y;
        y->rc=b;
        if(b)b->fa=y;
    }
    y->upt();x->upt();
}
inline void splay(node *x){
    static node* que[Maxn];
    static int tail;
    que[tail=1]=x;
    for(node* y=x;!isroot(y);y=y->fa)que[++tail]=y->fa;
    for(int i=tail;i>=1;i--)que[i]->pushdown();
    while(!isroot(x)){
        node *y=x->fa;
        if(!isroot(y)){
            if(which(y)^which(x))rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
}
inline void access(node *x){
    for(node *y=NULL;x;y=x,x=x->fa){
        splay(x);x->rc=y;x->upt();
        if(y)y->fa=x;
    }
}
inline void makeroot(node *x){
    access(x);splay(x);x->rev();
}
inline node* findmx(node *x,node *y){
    makeroot(x);access(y);splay(y);
    return y->mxid;
}
inline void Cut(node *x,node *y){
    makeroot(x);access(y);splay(y);
    y->lc->fa=NULL;y->lc=NULL;y->upt();
}
inline void Link(node *x,node *y){
    makeroot(x);x->fa=y;
}
int main(){
    n=read(),Acnt=read(),Bcnt=read(),q=read();
    for(int i=1;i<=Acnt;i++){
        A[i].x=read(),A[i].y=read(),A[i].w=read();
    }
    for(int i=1;i<=Bcnt;i++){
        B[i].x=read(),B[i].y=read(),B[i].w=read();
    }
    sort(A+1,A+Acnt+1);sort(B+1,B+Bcnt+1);
    for(int i=1;i<=n;i++)pos[i]=newnode(-INF,0,0);
    int head=1;
    for(int i=1;i<=n;i++)anc[i]=i;
    for(int i=1;i<n;i++){
        while(getanc(A[head].x)==getanc(A[head].y))++head;
        anc[getanc(A[head].x)]=getanc(A[head].y);
        node *t=newnode(A[head].w,A[head].x,A[head].y);
        Link(pos[A[head].x],t);Link(pos[A[head].y],t);
        sum+=A[head].w;++head;
    }
    head=1;int tot=0;
    for(int i=1;i<=n;i++)anc[i]=i;
    for(int i=1;i<n;i++){
        while(getanc(B[head].x)==getanc(B[head].y))++head;
        anc[getanc(B[head].x)]=getanc(B[head].y);
        Bnow[i]=B[head++];
    }
    sort(Bnow+1,Bnow+tot+1,cmpw);
    for(int i=1;i<n;i++){
        node *t=findmx(pos[Bnow[i].x],pos[Bnow[i].y]);
        if(t->val<=-INF){Bnow[i].low=INF;}
        else{
            Bnow[i].low=(Bnow[i].w-t->val+1)/2;
            Bnow[i].rpc=t->val;
            Cut(t,pos[t->x]);Cut(t,pos[t->y]);
            t=newnode(-INF,0,0);
            Link(pos[Bnow[i].x],t);Link(pos[Bnow[i].y],t);
        }
    }
    sort(Bnow+1,Bnow+n,cmplow);
    for(int i=1;i<=q;i++)qry[i].v=read(),qry[i].id=i;
    sort(qry+1,qry+q+1,cmpv);
    int cntB=0;head=0;
    for(int i=1;i<=q;i++){
        while(head<n-1&&Bnow[head+1].low<=qry[i].v){
            ++head;cntB++;
            sum+=Bnow[head].w;sum-=Bnow[head].rpc;
        }
        ans[qry[i].id]=sum+1ll*(n-1-2*cntB)*qry[i].v;
    }
    for(int i=1;i<=q;i++){
        W(ans[i]);putchar('\n');
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值