19-11-13-;

中午起来困傻了,写五分钟反思提下神智不轻的麦蒙

时间真快呀。

$$
\begin{array}{lr}
I\ wished\ upon\ a\ star\ and\ thought\ of\ you & \\
But\ it\ is\ a\ dream\ 'cause\ you're\ not\ here\ . & \\
&\ One\ Less\ Star
\end{array}
$$

记不清作者了

ZJ:

考试前平复心情……

开考简单看了一眼第一页(话说这是第一个把名字写在题目前的作者)

打$\text{vimrc}$

然后开T1。

……

六边形????????

不是很清楚。

于是先拿了特殊性质的10分。(做法正确!)

仿佛发现点什么东西。

今天风太巨了(奶风),于是有点闹肚,去厕所玩耍完善思路

觉得是贪心思路,先摆一个大正六边形,然后扩边。

手玩几个点都过了。

T2不会,先想了半天是从$f_i$到$i$还是从$i$到$f_i$建边。

T3先想了$Hash$,但是写了一会发现自己不会合并两侧的$hash$值

于是果断放弃,用 string 巨暴力拿到20。剪枝也没来得及打。

string 的几个函数。

1.erase(a,b)

可以从$a$开始删,删$b$个字符(本来以为左闭右开结果不是)

如$toot$ erase(2,2)  变为 $to$

2. substr(a,b)

返回从$a$开始,长度为$b$的子串

3. insert(a,str)

在$a$处插入一个字符串$str$,原序列依次后移。

如$toot$ insert(2,"toot") 变为$totootot$

14
Miemeng 100
00:00:19
30
00:00:19
20
00:00:20
150
00:00:20

这年头能不挂分就是谢天谢地了……

TJ:

怕咕咕咕之后死。

T1:

考场$1h$解决。

直接二分蒸馏变形正六边形下界,贪心扩边就ok。

复杂度:$\Theta(\log N)$

所以此题出到$N \leq 10^{18}$没有问题。(逃

对于那些$\Theta(1)$的大佬此题甚至可以$N \leq 10^{100000 \dots}$(高精预警(再逃

#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long

using namespace std;

LL fn,nans;
LL getval(int x){
	return 6ll*x*(x-1)/2+1;//这个是边长为k的蒸馏变形的占格数
}
LL getk(LL v){//二分边长
	LL l=1,r=100000;
	while(l<r){
		LL mid=(l+r+1)/2;
		if(getval(mid)<=v)l=mid;
		else r=mid-1;
	}
	return l;
}
int main(){
#ifndef LOCAL
	freopen("wall.in" ,"r",stdin);
	freopen("wall.out","w",stdout);
#endif
	ios_base::sync_with_stdio(false);
	cin>>fn;
	LL k=getk(fn);
	if(fn==getval(k)){//把10分稳住
		cout<<getval(k+1)-getval(k)<<endl;
	}
	else{
		k++;
		LL lft=fn-getval(k-1);
		if(k==2){
			cout<<getval(k)-getval(k-1)+lft+1<<endl;//二的贡献不好处理,特判掉
		}
		else{
			LL ede=k-2,lft=fn-getval(k-1);
			for(int i=1;i<6;i++){
				if(ede*i+i-1>=lft){
					cout<<getval(k)-getval(k-1)+i<<endl;
					return 0;
				}
			}
			cout<<getval(k+1)-getval(k)<<endl;
		}
	}
	
}

T2:

码死我了。

其实此题所用的是拓扑,$dfs$处理环,构造建图的思想。

但是其实不用真正拓扑,不用真正$dfs$,也不用真正建图(捂脸

但是我还是打了拓扑,$dfs$处理环,构造建图。

所以我累死了。

首先我们将$i$向$f_i$建边。

这样我们就可以用$i$的$C$去更新$f_i$的答案。

那么我们就已经处理好链的答案了。

下面我们要考虑环。

环很难搞。

首先如果环上的边不优我们可以直接拆环。

如果拆不掉

我们需要用两种值更新环上点的答案,

一种是用次小消耗(一定不在环上)代替(环上的)最小消耗所损失的答案。

另一种是没有其他代替方法,只能留下一个物品所损失的答案。

简单判下就可以了。

#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#define N 111111
#define LL long long

using namespace std;

struct Myqueue{
    int A[10*N];
    int f,b;
    Myqueue(){f=b=0;}
    void clear(){f=b=0;}
    void push(const int k){A[b++]=k;}
    void pop(){f++;}
    int front(){return A[f];}
    bool empty(){return f==b;}
    int size(){return b-f;}
}q;
struct SR{
    int f,t,next;
}rs[2*N];
int itn,fl[N],cnt=0;
int lop[N],deg[N];
vector <int> lp;
bool is_d[N];

LL op[N],cst[N],val[N],num[N];
LL minlp[N],minst[N],ans;

void add(int f,int t){
    rs[cnt].f=f;
    rs[cnt].t=t;
    rs[cnt].next=fl[f];
    fl[f]=cnt++;
}
void dfs(int k,const int id){
    lp.push_back(k);
    lop[k]=id;
    for(int i=fl[k];i!=-1;i=rs[i].next){
        int t=rs[i].t;
        minlp[t]=min(minlp[t],cst[k]);
        if(!lop[t]) dfs(t,id);
    }
}
void topsort(){
    for(int i=1;i<=itn;i++)
        if(deg[i]==0)
            q.push(i);
    while(!q.empty()){
        int f=q.front();q.pop();
        for(int i=fl[f];i!=-1;i=rs[i].next){
            int t=rs[i].t;
            deg[t]--;
            minst[t]=min(minst[t],cst[f]);
            if(deg[t]==0)
                q.push(t);
        }
    }
}
int main(){
#ifndef LOCAL
    freopen("goods.in" ,"r",stdin);
    freopen("goods.out","w",stdout);
#endif
    ios_base::sync_with_stdio(false);
    memset(fl,-1,sizeof fl);
    memset(minlp,0x3f,sizeof minlp);
    memset(minst,0x3f,sizeof minst);
    cin>>itn;
    for(int i=1;i<=itn;i++){
        cin>>op[i]>>cst[i]>>val[i]>>num[i];
        add(i,op[i]);
        deg[op[i]]++;
    }
    topsort();
    for(int i=1;i<=itn;i++){
        if(deg[i]==0){
            if(val[i]>minst[i])
                ans+=(val[i]-minst[i])*num[i];
        }
        else if(!lop[i]){//cout<<i<<endl;
            lp.clear();
            dfs(i,i);
            if(lp.size()==1){
                LL aminn=min(minlp[i],minst[i]);
                if(aminn<val[i])
                    ans+=(val[i]-aminn)*num[i];
                continue;
            }
            bool des=0;
            for(int i=0;i<(int)lp.size();i++){
                if(min(minlp[lp[i]],minst[lp[i]])>val[lp[i]]){
                    //cout<<"Kill!"<<i<<endl;
                    is_d[lp[i]]=1;
                    des=1;
                }
                else if(minst[lp[i]]<=minlp[lp[i]]){
                    ans+=(val[lp[i]]-minst[lp[i]])*num[lp[i]];
                    is_d[lp[i]]=1;
                    des=1;
                }
            }
            //cout<<des<<endl;
            if(des){
                for(int i=0;i<(int)lp.size();i++){
                    if(!is_d[lp[i]])
                        ans+=(val[lp[i]]-minlp[lp[i]])*num[lp[i]];
                    else is_d[lp[i]]=0;
                }
            }
            else{
                LL minans=LLONG_MAX,minval=LLONG_MAX;
                for(int i=0;i<(int)lp.size();i++){
                    ans+=(val[lp[i]]-minlp[lp[i]])*num[lp[i]];
                    minans=min(minans,minst[lp[i]]-minlp[lp[i]]);
                    minval=min(minval,val[lp[i]]-minlp[lp[i]]);
//                    cout<<"Va:"<<val[lp[i]]<<endl;
//                    cout<<"Mp:"<<minlp[lp[i]]<<endl;
//                    cout<<"De:"<<val[lp[i]]-minlp[i]<<endl;
                }
                if(minans<=minval)
                    ans-=minans;
                else
                    ans-=minval;
            }
        }
    }
    cout<<ans<<endl;
}

 

posted @ 2019-11-13 11:40  Miemeng_麦蒙  阅读(252)  评论(0编辑  收藏  举报

小麦在雨中,蒙蒙的雾气

麦蒙不想有人骚扰他,如果有必要 联系 QQ:1755601414

如果你嫌广告大,那就喷我吧,不是博客园的锅。