【UNR #3】Day1

A

首先按s从小到大排序。
考虑枚举右端点r,往前扫l,用一个小根堆维护前m大。
一个显然的优化:当r被弹出堆时就可以停止扫描了,因为此时一定可以通过往左移动r来使得答案更优。
然后我们发现如果一个点i在r往左扫描时没有入堆,那么在r+1往左扫描时也不会入堆。因此可以直接删去。
用链表维护一下剩余可能入堆的点即可。
复杂度 O(nmlogm) O ( n m l o g m )

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 200010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,ds,dv,pre[N];
ll ans=0;
struct Icefox{
    int s,v;
    friend bool operator<(Icefox a,Icefox b){return a.s<b.s;}
}a[N];
inline ll cal(ll x,int k){
    return k==1?x:x*x;
}
int main(){
//  freopen("ex_B3.in","r",stdin);
    n=read();m=read();ds=read();dv=read();
    for(int i=1;i<=n;++i) a[i].s=read(),a[i].v=read(),pre[i]=i-1;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;++i){
        priority_queue<int,vector<int>,greater<int> >q;
        ll sum=0;int x=i,lst=i;
        for(int j=1;j<=m;++j) q.push(0);
        while(x){
            int y=q.top();
            if(y<a[x].v){
                sum+=a[x].v-y;q.pop();q.push(a[x].v);
                if(q.top()>a[i].v) break;
                ans=max(ans,cal(sum,dv)-cal(a[i].s-a[x].s,ds));
            }else pre[lst]=pre[x];
            lst=x;x=pre[x];
        }
    }printf("%lld\n",ans);
    return 0;
}

B

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,fa[N],dis[N];
vector<int>Son[N],ans[N];
inline void dfs(int x){
    for(int i=0;i<Son[x].size();++i){
        int y=Son[x][i];dfs(y);dis[x]=max(dis[x],dis[y]+1);
    }
}
struct Cmp{
    bool operator()(int x,int y){
        return dis[x]<dis[y];
    }
};
int main(){
//  freopen("ex_todotree3.in","r",stdin);
    n=read();m=read();
    for(int i=2;i<=n;++i) fa[i]=read(),Son[fa[i]].push_back(i);
    dfs(1);priority_queue<int,vector<int>,Cmp>q;q.push(1);int cnt=0;
    while(!q.empty()){
        ++cnt;
        for(int i=1;i<=m;++i){
            int x=q.top();q.pop();ans[cnt].push_back(x);if(q.empty()) break;
        }for(int i=0;i<ans[cnt].size();++i){
            int x=ans[cnt][i];
            for(int j=0;j<Son[x].size();++j) q.push(Son[x][j]);
        }
    }printf("%d\n",cnt);
    for(int i=1;i<=cnt;++i){
        printf("%d ",(int)ans[i].size());
        for(int j=0;j<ans[i].size();++j) printf("%d ",ans[i][j]);puts("");
    }return 0;
}

C

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define mod 998244353
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,h[N],num=0,rt[N],owo=0,ans=0;
struct edge{
    int to,next,val;
}data[N<<1];
struct node{
    int ls,rs,f[2][2],x;
    inline int ans(){
        ll res=(ll)(f[0][0]+1)*f[0][1]+(ll)f[1][0]*f[1][1];res%=mod;return res;
    }
}tr[N*20];
vector<int>a[N];
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline node unit(int l,int r){
    node res;res.x=0;res.f[0][1]=0;res.f[1][1]=0;
    int half=r-l+1>>1;
    res.f[1][0]=res.f[0][0]=half;
    if((r-l+1)&1) res.f[l&1][0]++;return res;
}
inline void pushup(int p,int l,int mid,int r){
    node ls=tr[p].ls?tr[tr[p].ls]:unit(l,mid),rs=tr[p].rs?tr[tr[p].rs]:unit(mid+1,r);
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j)
            tr[p].f[i][j]=ls.f[i][j]+rs.f[i][j^ls.x];
    tr[p].x=(ls.x+rs.x)&1;
}
inline void change(int &p,int l,int r,int x){
    if(!p) p=++owo;if(l==r){tr[p].f[l&1][1]++;tr[p].x^=1;return;}
    int mid=l+r>>1;
    if(x<=mid) change(tr[p].ls,l,mid,x);
    else change(tr[p].rs,mid+1,r,x);pushup(p,l,mid,r);
}
inline int merge(int p1,int p2,int l,int r){
    if(!p1||!p2) return p1+p2;int mid=l+r>>1;
    tr[p1].ls=merge(tr[p1].ls,tr[p2].ls,l,mid);
    tr[p1].rs=merge(tr[p1].rs,tr[p2].rs,mid+1,r);pushup(p1,l,mid,r);return p1;
}
inline void dfs(int x,int Fa){
    for(int i=0;i< a[x].size();++i) change(rt[x],1,m,a[x][i]);
    for(int i=h[x];i;i=data[i].next){
        int y=data[i].to;if(y==Fa) continue;
        dfs(y,x);inc(ans,(ll)data[i].val*tr[rt[y]].ans()%mod);
        rt[x]=merge(rt[x],rt[y],1,m);
    }
}
int main(){
//  freopen("ex_c3.in","r",stdin);
    n=read();m=read();
    for(int i=1;i< n;++i){
        int x=read(),y=read(),val=read();
        data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;
        data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].val=val;
    }for(int i=1;i<=m;++i) a[read()].push_back(i);dfs(1,0);
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值