新的篇章~(exchange arguments贪心)

是这样的,这个是一个不错的东西,我将花费一个晚上加半个早上来做,看看能做哪是哪吧~
这种贪心的思路是更进一步的,具体而言是对于两个有所联系的元素(比如承重与重量),将其化成关系式后比较后再化成另一种形式,大佬说:在这里插入图片描述
来一道:P1080 [NOIP2012 提高组] 国王游戏,是这样的,就是要按着那东西推导一下,然后发现a*b大的在前面就行了。所以我不想打高精,所以…

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e3+5;
int sadfnasouidbnxhjklvxkhjvbadijjasbfhasfbashlaxckhv,asf;
int naiduvbxijlvbaiubadsiunkvhxcbvioaxcnvhadshsd;
int now[4*maxn],ans[4*maxn],afe[4*maxn];//注意开大数组
int len=1,bit=0,culen=1;
struct Node{
    int a,b;
    bool friend operator < (const Node &A, const Node &B){
        return A.a*A.b<B.a*B.b;//按左右手乘积从小到大排序
    }
}node[maxn];
void mul(int x){//高精度乘法
    for(int i=1;i<=len;i++)now[i]*=x;//每一位都乘以该数
    for(int i=1;i<=len;i++)now[i+1]+=now[i]/10,now[i]%=10;//进位
    if(now[len+1])len++;//进位后首位加长
    while(now[len]>10)now[len+1]+=now[len]/10,now[len]%=10,len++;//首位继续加长
}
void exc(int x){//高精度除法
    int cur=0,rem=0,f=0;bit=0;
    for(int i=len;i>=1;i--){//模拟除法竖式
        cur=now[i]+rem*10;//计算当前被除数的值,rem是余数
        if(!f&&cur<x)rem=cur;//还没有出现过非零位且该位也为0,余数即为被除数
        else f=1,afe[++bit]=cur/x,rem=cur%x;//记录该位上的数并更新余数
    }
    if(!bit)afe[1]=0,bit=1;//如果作除后得到的数位数为0,说明作除后得到的值为0
}
void upd(){//更新答案
    if(bit>culen){//当前大数的位数大于答案位数,则当前数一定大于答案
        for(int i=1;i<=bit;i++)ans[i]=afe[i];//更新答案数值
        culen=bit;//更新答案位数
    }
    else if(bit==culen){//当前大数的位数等于答案的位数
        for(int i=1;i<=bit;i++){
            if(afe[i]>ans[i]){//如果当前位该数要比答案大
                for(int i=1;i<=bit;i++)ans[i]=afe[i];//更新答案数值
                break;
            }
        }
    }
}
signed main(){
    int n;
    cin>>n;
    for(int i=1;i<=10000001;i++) ;
    cin>>node[0].a>>node[0].b;//国王
    for(int i=1;i<=n;i++)cin>>node[i].a>>node[i].b;//大臣
    sort(node+1,node+1+n);//结构体排序
    now[1]=1,ans[1]=0;
    for(int i=1;i<=n;i++){
        mul(node[i-1].a);//累乘至前一位大臣左手
        exc(node[i].b);//除以当前大臣右手
        upd();//更新答案
    }
    for(int i=1;i<=culen;i++)cout<<ans[i];//打印答案
    return 0;
}

URAL - 1522 呃这一题是英语题目所以一开始没看懂,转载了别人说的。
1)如果x比y先生产,根据题意中的max(bi)<=min(ai) or max(bi)<=min(ci)条件,我们可以计算出则总时间t=x.a+y.c+max(x.b+x.c,y.a+y.b);
2)如果y比x先生产,根据题意中的max(bi)<=min(ai) or max(bi)<=min(ci)条件,我们可以计算出则总时间t=y.a+x.c+max(y.b+y.c,x.a+x.b);

#include<bits/stdc++.h>
#define int long long 
using namespace std;
int n,m;
struct node
{
	int a,b,c,num;
};node e[2000001];
bool cmp(const node &x,const node &y)
{
	int p=x.a+y.c+max(x.b+x.c,y.a+y.b);
	int q=y.a+x.c+max(y.b+y.c,x.a+x.b);
	if(p!=q) return p<q;
	return x.a<y.a;	
}
signed main()
{
	while(scanf("%lld",&n)!=EOF)
	{
		for(int i=1;i<=n;i++) scanf("%lld%lld%lld",&e[i].a,&e[i].b,&e[i].c),e[i].num=i;
		sort(e+1,e+n+1,cmp);int aa=0,bb=0,cc=0;
		for(int i=1;i<=n;i++) aa+=e[i].a,bb=max(bb,aa)+e[i].b,cc=max(cc,bb)+e[i].c;
		printf("%lld\n",cc);
		for(int i=1;i<=n;i++) printf("%lld ",e[i].num);
		printf("\n");
	}
	return 0;
}

下一个~Google Code Jamcf上的捏,突然想见她QWQ,事实上这道题要加上一个背包,但我觉得好爽!
其实想着过几天再补的QWQ。
求求了,Manga Market嗯这个看看吧~

//对于排列,并不多说什么,必要的是以下的dp操作,用背包维护后再二分的选取x为0的那些!
//手算发现,商店的时间每次都至少翻一倍,所以只需要枚举至log(T)就行 
//最后再二分查找一下,若当前选择i台那么剩下的时间能干什么 
#include<bits/stdc++.h>
#define int long long 
using namespace std;
int n,m,b[400011],tot1=0,tot2=0,T,ans=0;
int f[400011];
struct node
{
	int x,y;
};node a[400011];
bool cmp(const node &x,const node &y)
{
	return x.x*(y.y+1)>y.x*(x.y+1);
}
 main()
{
	scanf("%lld%lld",&n,&T);
	for(int i=1;i<=n;i++)
	{
		int x,y;scanf("%lld%lld",&x,&y);
		if(x==0) b[++tot2]=y+1;
		else a[++tot1]={x,y};
	}
	sort(a+1,a+tot1+1,cmp);sort(b+1,b+tot2+1);
	for(int i=1;i<=35;i++) f[i]=T+1;
	for(int i=1;i<=tot1;i++)
	{
		for(int j=35;j>=1;j--) f[j]=min(f[j],(f[j-1]+1)*(a[i].x+1)+a[i].y);
	} 
	for(int i=1;i<=tot2;i++) b[i]+=b[i-1];											
	for(int i=0;i<=35;i++)
	{
		if(f[i]>T) continue;
		int x=0;
		if(tot2) x=upper_bound(b+1,b+tot2+1,T-f[i])-(b+1);
		ans=max(ans,i+x);
	}
	printf("%lld",ans);
	return 0;
 } 

[AGC023F] 01 on Tree最后一个咯。比较的是一个点的1先插入后会对多少个0产生贡献那么其实可以看到 x.cnt0y.cnt1<x.cnt1y.cnt0,这样的情况下相对是最好的。

//考虑用堆合并,拿并查集维护。 
#include<bits/stdc++.h>
#define int long long 
using namespace std;
int n,m,cnt[2000001][3],ans=0,ff[2000001],fa[2000001];
struct node
{
	int cnt0,cnt1,id;
	friend bool operator < (const node &x,const node &y)
	{
		return x.cnt0*y.cnt1<x.cnt1*y.cnt0;
	};
};priority_queue <node > q;
int findfa(int x) 
{
	if(fa[x]==x) return x;
	return fa[x]=findfa(fa[x]);
}
signed main()
{
	scanf("%lld",&n);
	for(int i=2;i<=n;i++) scanf("%lld",&ff[i]);
	for(int i=1;i<=n;i++) 
	{
		int x;scanf("%lld",&x);
		cnt[i][x]++;
	}
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=2;i<=n;i++) q.push({cnt[i][0],cnt[i][1],i});
	while(q.size()!=0)
	{
		node x=q.top();q.pop();
		int fx=findfa(x.id),cnt0=x.cnt0,cnt1=x.cnt1;
		if(cnt0!=cnt[fx][0]||cnt1!=cnt[fx][1]) continue ;//如果这个点之前被合并过了
		int y=findfa(ff[fx]);ans+=cnt[y][1]*cnt[fx][0];
		cnt[y][0]+=cnt[fx][0];cnt[y][1]+=cnt[fx][1];
		fa[fx]=y;
		if (y>1) q.push({cnt[y][0],cnt[y][1],y});
	}
	printf("%lld",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值