东方博宜oj 提高答案 合集

点个赞谢谢!!!

1542 - 小X算排名

#include 
using namespace std;
int N,a[100010],ra[100010];
bool cmp(int x,int y)
{
    return x>y;
}
int efl(int x)
{
    int l=1,r=N,mid;
    while(l<=r)
    {
        mid=l+r>>1;
        if(a[mid]<=x)r=mid-1;
        else l=mid+1;
    }
    return l;
}
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d",&a[i]);
        ra[i]=a[i];
    }
    //这个时候需要排序
    sort(a+1,a+N+1,cmp);
 
    for(int i=1;i<=N;i++)
    {
        printf("%d\n",efl(ra[i]));
    }
 
    return 0;
}

1561 - 买木头

#include 
using namespace std;
struct node {
	int len;
	int num;
};
node a[10010];
int n, m, ma, c;
int main () {
	cin >> n >> m >> a[1].len >> a[1].num;
	ma = a[1].len;
	for (int i = 2; i <= n; i ++) {
		a[i].len = ((a[i - 1].len * 37011 + 10193) % 10000) + 1;
		a[i].num = ((a[i - 1].num * 73011 + 24793) % 100) + 1;
		if (a[i].len > ma) ma = a[i].len;
	}
	for (int i = ma; i >= 1; i --) {
		c = 0;
		for (int j = 1; j <= n; j ++) {
			c += a[j].len / i * a[j].num;
			if (c >= m) {
				cout << i;
				return 0;
			}
		}
	}
	return 0;
}

1909 - 跳石头

#include
#include
using namespace std;
int leng,n,m,a[50002];
bool check(int x){
	int last=0;
	int sum=0;
	for(int i=1;i<=n;i++){
		if(a[i]-last>=x){
			last=a[i];
		}else{
			sum++;
		}
	}
	if(leng-last>leng>>n>>m;
	int l=1,r=leng;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	while(r>l){
		int mid=(l+r+1)>>1;
		if(check(mid)){                //如果间隔为mid可以实现
			l=mid;
		}else{
			r=mid-1;
		}
	}
	cout<

1923 - 躲避拥堵的最佳路线

//  1923 - 躲避拥堵的最佳路线 ---并查集,二分答案
// 来源: 东方博宜oj  oj.czos.cn
#include
using namespace std;
/*
  经过道路的拥挤度的最大值最小(二分答案)
*/
 
/*思路
1,二分最大拥挤度:l=min(拥挤度),r=max(拥挤度);
2,check(mid):检验当最大拥挤度为mid时,能否从s区到t区;
   (1)将所有道路中拥挤度<=mid的道路修起来(合并)
   (2)查询s和t是否在一个集合
3,求二分的左边界
代码*/
const int N=1e4+10;
int n,m,s,t;
int fa[N];
int l=INT_MAX,r=INT_MIN,mid;
struct node
{
    int x,y,len;
}a[2*N];
int findd(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=findd(fa[x]);
}
void mergee(int x,int y)
{
    int fx=findd(x);
    int fy=findd(y);
    if(fx!=fy) fa[fx]=fy;
}
bool check(int mid)
{
    //初始化
    for(int i=1;i<=n;i++) fa[i]=i;
    //修路
    for(int i=1;i<=m;i++)
    {
        if(a[i].len<=mid) mergee(a[i].x,a[i].y);
    }
    // 判断s能否去t,如果在一个集合就能去
    return findd(s)==findd(t);
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        cin>>a[i].x>>a[i].y>>a[i].len;
        l=min(l,a[i].len);
        r=max(r,a[i].len);
    }
    //二分答案
    while(l<=r)
    {
        mid=l+r>>1;
        if(check(mid)) r=mid-1;
        else l=mid+1;
    }
    cout<< l;
    return 0;
}

1820 - 金明的预算方案

#include 
using namespace std;
const int N = 32010;
const int M = 60;
typedef pair PII;
vector  qr[M];
#define pb(x) push_back(x)
PII own[M];
int n,m;
#define mk(x,y) make_pair(x,y)
int f[N];
int main () {
	cin >> n >> m;
	for(int i = 1;i <= m; ++i) {
		int v,p,q;
		cin >> v >> p >> q;p *= v;
		if(q == 0) own[i] = mk(v,p);
		else {
			qr[q].pb(mk(v,p));
		}
	}
	for(int i = 1;i <= m; ++i) {
		for(int j = n;j >= 0; --j) {
			for(int k = 0;k < (1 << qr[i].size()); ++k) {
				int l = own[i].first;
				int r = own[i].second;
				//cout << l << ' '<< r << endl;
				for(int p = 0;p < (qr[i].size()); ++p) {
					if(k >> p & 1) {
						l += qr[i][p].first;
						r += qr[i][p].second;
					}
				}
				if(j >= l) f[j] = max(f[j],f[j - l] + r);
			}
		}
	}
	//for(int i = 0;i <= m; ++i) cout << f[i] << ' ';
	cout << f[n] << endl;
	return 0;
}

1930 - 关押罪犯

// 1930 - 关押罪犯 --- 种类并查集
// 来源: 东方博宜oj  oj.czos.cn
// 补充:noip提高组复赛 并查集
#include
using namespace std;
const int N=2e4+10,M=1e5+10;
int n,m;
// a和b是敌人,怨气值为c
struct node
{
    int a,b,c;
}e[M];
int f[2*N];
// 查询
int findd(int x)
{
    return x==f[x]? x:f[x]=findd(f[x]);
}
// 合并
void mergee(int x,int y)
{
    int fx=findd(x);
    int fy=findd(y);
    if(fx!=fy) f[fx]=fy;
}
// 将怨气值降序排序
bool cmp(node x1,node x2)
{
    return x1.c>x2.c;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n*2;i++) f[i]=i;   //初始化
    for(int i=1;i<=m;i++)  cin>>e[i].a>>e[i].b>>e[i].c;
    // 将怨气值降序排序,从最大的开始拆分
    sort(e+1,e+1+m,cmp);
    for(int i=1;i<=m;i++)
    {
        // 如果发现2个人已经在一座监狱,必定有冲突
        if(findd(e[i].a)==findd(e[i].b))
        {
            cout<< e[i].c;
            return 0;
        }
        else
        {
            // 将每个人和其假想的好友和合并
            mergee(e[i].b+n,e[i].a);
            mergee(e[i].a+n,e[i].b);
        }
    }
    cout<< 0;
    return 0;
}

1126 - 英文翻译

#include
#include
using namespace std;
int list[4]={1000000000,1000000,1000,100};
char s[4][10]={"billion","million","thousand","hundred"};
void read_1(int n)
{
	switch(n)
	{
		case 1:cout<<"one ";break;
		case 2:cout<<"two ";break;
		case 3:cout<<"three ";break;
		case 4:cout<<"four ";break;
		case 5:cout<<"five ";break;
		case 6:cout<<"six ";break;
		case 7:cout<<"seven ";break;
		case 8:cout<<"eight ";break;
		case 9:cout<<"nine ";break;
		case 10:cout<<"ten ";break;
		case 11:cout<<"eleven ";break;
		case 12:cout<<"twelve ";break;
		case 13:cout<<"thirteen ";break;
		case 14:cout<<"fourteen ";break;
 		case 15:cout<<"fifteen ";break;
 		case 16:cout<<"sixteen ";break;
 		case 17:cout<<"seventeen ";break;
		case 18:cout<<"eighteen ";break;
		case 19:cout<<"nineteen ";break;
		default:break;
	}
}
void read_10(int n)
{
	int t=n/10;
	if(t>1)
	{
		switch(t)
		{
			case 2:cout<<"twenty ";break;
			case 3:cout<<"thirty ";break;
			case 4:cout<<"forty ";break;
			case 5:cout<<"fifty ";break;
			case 6:cout<<"sixty ";break;
			case 7:cout<<"seventy ";break;
			case 8:cout<<"eighty ";break;
			case 9:cout<<"ninty ";break;	
		}
		n%=10;
		read_1(n);
	}
	else read_1(n);
}
void Read(int n)
{
	if(n<100)
	{
		read_10(n);return;
	}
	int i=0;
	while(n>0&&i<4)
	{
		int t=n/list[i];
		if(t>0)
		{
			Read(t);
			cout<0)
	{
		cout<<"and ";
		read_10(n);
	}
	return;
}
int main()
{
	int n;
	cin>>n;
	Read(n);
	return 0;
}

1855 - 删除多余括号

#include
using namespace std;
typedef pair PII; // right), left(

stack sta;
vector v;
string s;

map signlevel;


bool check(int a, int b) {
	stack tmp; // 若tmp栈中存在数,说明现在还处于内部括号的范围中,不能统计符号 
	vector sign;
	char leftsign = s[a-1], rightsign = s[b+1];
	int mnlv = 3; // 含义为括号内符号优先级最低是多少 
	int rslv = signlevel[rightsign]; // 右侧符号的优先级 
	
	for(int i = a+1;i <= b-1;i ++) {
		if(s[i] == ' ') continue;
		if(tmp.empty()) { // 空了 
			if(s[i] == '(') tmp.push(1); // 若遍历到左括号,则入栈 
			else if(!isalpha(s[i])) sign.push_back(s[i]); // 不是字母,就说明是外层括号内的有效符号了 
		} else if(s[i] == ')') tmp.pop(); // 内层右括号出栈 
	}
	
	for(int i = 0;i < sign.size();i ++) mnlv = min(mnlv, signlevel[sign[i]]); 
	
	if(mnlv < rslv) return false;
	if(((leftsign == '-' || leftsign == '*') && mnlv != 2) || leftsign == '/') return false;
	return true;
}


int main()
{
	// 每个符号的优先级 
	signlevel[' '] = 0; signlevel['('] = 0; signlevel[')'] = 0;
	signlevel['+'] = 1; signlevel['-'] = 1; signlevel['*'] = 2; signlevel['/'] = 2; 
	
	while(cin>>s) {
		v.clear(); 
		int n = s.size();
		s = ' '+s+' '; // 开头和结尾加空格,就是防止越界的作用 
		for(int i = 1;i <= n;i ++) 
		if(s[i] == '(') sta.push(i); // 左括号入栈 
		else if(s[i] == ')') v.push_back(PII(i, sta.top())), sta.pop(); // 遇到右括号,左括号出栈,记录括号配对信息 
		sort(v.begin(), v.end()); // 排序 
		
//		for(int i = 0;i < v.size();i ++) cout << v[i].second << ' ' << v[i].first << endl;
		
		for(int i = 0;i < v.size();i ++) {
			int a = v[i].second, b = v[i].first;
			if(check(a, b)) s[a] = s[b] = ' '; // 去括号 
		}
		
		for(int i = 1;i <= n;i ++) if(s[i] != ' ') cout << s[i]; puts("");
	}
}

1923 - 躲避拥堵的最佳路线

//  1923 - 躲避拥堵的最佳路线 ---并查集,二分答案
// 来源: 东方博宜oj  oj.czos.cn
#include
using namespace std;
/*
  经过道路的拥挤度的最大值最小(二分答案)
*/
 
/*思路
1,二分最大拥挤度:l=min(拥挤度),r=max(拥挤度);
2,check(mid):检验当最大拥挤度为mid时,能否从s区到t区;
   (1)将所有道路中拥挤度<=mid的道路修起来(合并)
   (2)查询s和t是否在一个集合
3,求二分的左边界
代码*/
const int N=1e4+10;
int n,m,s,t;
int fa[N];
int l=INT_MAX,r=INT_MIN,mid;
struct node
{
    int x,y,len;
}a[2*N];
int findd(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=findd(fa[x]);
}
void mergee(int x,int y)
{
    int fx=findd(x);
    int fy=findd(y);
    if(fx!=fy) fa[fx]=fy;
}
bool check(int mid)
{
    //初始化
    for(int i=1;i<=n;i++) fa[i]=i;
    //修路
    for(int i=1;i<=m;i++)
    {
        if(a[i].len<=mid) mergee(a[i].x,a[i].y);
    }
    // 判断s能否去t,如果在一个集合就能去
    return findd(s)==findd(t);
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        cin>>a[i].x>>a[i].y>>a[i].len;
        l=min(l,a[i].len);
        r=max(r,a[i].len);
    }
    //二分答案
    while(l<=r)
    {
        mid=l+r>>1;
        if(check(mid)) r=mid-1;
        else l=mid+1;
    }
    cout<< l;
    return 0;
}

你可能感兴趣的:(算法,c++)