膜拜神牛

题目描述

Garfield听说OI班有N头神牛,每头神牛有两个属性,算法能力和思维能力,分别以Ai和Bi表示。如果神牛i和神牛j满足Ai ≥ Aj且Bi ≤ Bj,那么两位神牛会互相膜拜。Garfield认为膜拜是不和谐的,所以她想知道,最大的不存在膜拜关系的子集大小。

输入

第一行,一个整数N,表示神牛数量。
接下来N行,每行两个整数Ai和Bi,表示神牛的算法能力和思维能力。
输出

一个整数,表示最大的子集大小。
输入样例

3
1 1
2 3
3 2
输出样例

2
说明

数据规模
对于40%的数据,N ≤ 103,
对于100%的数据,N ≤ 105。

.
.
.
.
.
分析
排序后可把问题转化为求最长下降子序列

.
.
.
.
.
程序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct edge
{
	int a,b;
}w[100010];

int n,a[200000],ans=0,f[200000];

bool cmp(edge x,edge y)
{
	if (x.a!=y.a) return x.a>y.a; else return x.b>y.b;
}

void lds() 
{
    memset(f,127,sizeof(f));
    for (int i=1;i<=n;i++)
		if (a[i]<f[ans])
        {
            ans++;
            f[ans]=a[i];
        } else
        {
    		int l=1,r=ans;
            while (l<r)
            {
                int mid=(l+r)/2;
                if (f[mid]<=a[i]) r=mid; else l=mid+1;
            }
            f[l]=a[i];
        }
}


int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d%d",&w[i].a,&w[i].b);
	sort(w+1,w+n+1,cmp);
	for (int i=1;i<=n;i++)
		a[i]=w[i].b;
	lds();
	printf("%d",ans);
	return 0;
}
#include <bits/stdc++.h> using namespace std; const int o = 5e5; const int N = 5e5+10; const int INF = 0x3f3f3f3f; int a[N]; int s[N],dp[N]; int tree[N << 2]; int lazy[N <<2]; int pre[N]; int t[N << 2]; int n,m; void up(int node, int l, int r, int pos, int val) { if (l == r) { t[node] = min(t[node], val); } else { int mid = (l + r) >> 1; if (pos <= mid) up(node << 1, l, mid, pos, val); else up(node << 1 | 1, mid + 1, r, pos, val); t[node] = min(t[node << 1], t[node << 1 | 1]); } } int qu(int node, int l, int r, int ql, int qr) { if (r < ql || l > qr) return INF; if (ql <= l && r <= qr) return t[node]; int mid = (l + r) >> 1; return min( qu(node << 1, l, mid, ql, qr), qu(node << 1 | 1, mid + 1, r, ql, qr) ); } bool Inrange(int L,int R,int l,int r){ return (L >= l) && (R <= r); } bool Outrange(int L,int R,int l,int r){ return (L > r) || (R < l); } void pushup(int node){ tree[node] = min(tree[node << 1],tree[node << 1|1]); } int build(int node,int left,int right){ if(left == right){ tree[node] = 0x3f3f3f3f; } else{ int mid = (left+right) >> 1; build(node << 1,left,mid); build(node << 1|1,mid+1,right); pushup(node); } } //void up(int idx, int val) { // for (; idx > 0;) { // t[idx] = min(t[idx], val); // idx -= idx & -idx; // } //} // //int qu(int idx) { // int res = INF; // for (; idx <= N; ) { // res = min(res, tree[idx]); // idx += idx & -idx; // } // return res; //} int maketag(int node,int len,int val){ tree[node] = min(tree[node], val); lazy[node] = min(lazy[node], val); } int pushdown(int node,int left,int right){ if(lazy[node] != 0x3f3f3f3f){ int mid = (left + right) >> 1; maketag(node << 1,mid-left+1,lazy[node]); maketag(node << 1|1,right-mid,lazy[node]); lazy[node] = 0x3f3f3f3f; } } int query(int node,int left,int right,int l,int r){ if(Inrange(left,right,l,r)){ return tree[node]; } else{ if(!Outrange(left,right,l,r)){ int mid = (left+right) >> 1; pushdown(node,left,right); return min(query(node << 1,left,mid,l,r) , query(node <<1|1,mid+1,right,l,r)); } else return 0x3f3f3f3f; } } //void update(int node,int L,int R,int l,int r,long long int val){ // if(Inrange(L,R,l,r)){ // maketag(node,R-L+1,val); // } // else{ // if(!Outrange(L,R,l,r)){ // int M = (L+R) >> 1; // pushdown(node,L,R); // update(node << 1,L,M,l,r,val); // update(node << 1|1,M+1,R,l,r,val); // pushup(node); // } // } //} void update_point(int node, int left, int right, int pos, int k) { if (left == right) { tree[node] = min(tree[node],k); } else { int mid = (left + right) >> 1; if (pos <= mid) update_point(node << 1, left, mid, pos, k); else update_point(node << 1 | 1, mid + 1, right, pos, k); pushup(node); } } //int main(){ // ios::sync_with_stdio(false); // cin.tie(0); // cout.tie(0); // cin >> n >>m; // for(int i = 1;i<=n;i++){ // int val; // cin >>val; // if(val == 2) val = -1; // a[i] = val; // s[i] = s[i-1] +a[i]; // if(a[i] == a[i-1]){ // pre[i] = pre[i-1] +1; // } // else pre[i] = 1; // } // memset(dp, 0x3f, sizeof(dp)); // dp[0] = 0; // build(1,1,n); // update_point(1,1,n,1,dp[0]); //// for (int i = 1; i <= n; i++) { //// int min_dp = N; //// for (int j = max(0,i-100); j < i; j++) { //// if (s[i] - m <= s[j] && s[j] <= s[i] + m) { //// min_dp = min(min_dp, dp[j]); //// } //// } //// if (min_dp != N) { //// dp[i] = min(dp[i], min_dp + 1); //// } //// dp[i] = min(dp[i], dp[i - pre[i]] + 1); //// update_point(1, 1, n, i + 1, dp[i]); //// } // for(int i = 1;i<=n;i++){ // int ql = max(-o, s[i] - m); // int qr = min(o * 2, s[i] + m); // ql += o; // qr += o; // int min_dp = INF; // for (int j = qr + 1; j > 0; j -= j & -j) { // min_dp = min(min_dp, t[j]); // } // for (int j = ql; j > 0; j -= j & -j) { // min_dp = min(min_dp, t[j]); // } // if (min_dp != INF) { // dp[i] = min(dp[i], min_dp + 1); // } // up(s[i] + o, dp[i]); // if (min_dp != N) { // dp[i] = min(dp[i], min_dp + 1); // } // dp[i] = min(dp[i], dp[i - pre[i]] + 1); // update_point(1, 1, n, i + 1, dp[i]); // } // // //// for(int i = 1;i<=n;i++){ //// for(int j = 0;j<i;j++){ //// if(s[i]-m <= s[j] && s[j] <= m+s[i]){ //// update_point(1,1,n,i,min(dp[i],dp[j]+1)); //// } //// } //// update_point(1,1,n,i,min(query(1,1,n,i-pre[i],i-1),dp[i])); //// } //// cout << dp[n]; // cout << dp[n]; // return 0; //} int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; for (int i = 1; i <= n; ++i) { int val; cin >> val; if (val == 2) val = -1; a[i] = val; s[i] = s[i - 1] + a[i]; if (i > 1 && a[i] == a[i - 1]) { pre[i] = pre[i - 1] + 1; } else { pre[i] = 1; } } memset(dp, 0x3f, sizeof(dp)); memset(t,N,sizeof(t)); dp[0] = 0; up(1, 0, N - 1, s[0] + o, dp[0]); for (int i = 1; i <= n; ++i) { int min_dp = qu(1, 0, N - 1,s[i] - m+ o, s[i] + m + o); if (min_dp != INF) dp[i] = min(dp[i], min_dp + 1); if (i - pre[i] >= 0) dp[i] = min(dp[i], dp[i - pre[i]] + 1); up(1, 0, N - 1, s[i] + o, dp[i]); } cout << dp[n] << endl; return 0; }题目背景 某校 2015 届有两位 OI ,yyy 和 c01。 题目描述 全校除他们以外的 N 名学生,每人都会膜拜他们中的某一个人。现在老师要给他们分宿舍了。但是,问题来了: 同一间宿舍里的人要么膜拜同一位大,要么膜拜 yyy 和 c01 的人数的差的绝对值不超过 M。否则他们就会打起来。 为了方便,老师让 N 名学生站成一排,只有连续地站在一起的人才能分进同一个宿舍。 假设每间宿舍能容纳任意多的人,请问最少要安排几个宿舍? 输入格式 第一行,两个正整数 N 和 M。 第 2,3,⋯,N+1 行,每行一个整数,是 1 或 2,第 i 行的数字表示从左往右数第 i−1 个人膜拜的大,1 表示 yyy,2 表示 c01。 输出格式 一行,一个整数,表示最少要安排几个宿舍。 输入输出样例 输入 #1复制 5 1 1 1 2 2 1 输出 #1复制 1
最新发布
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值