[TIOJ] 1316. 晶片設計

題目連結:http://tioj.infor.org/problems/1316
一開始想錯方向,以為是有一堆開頭跟結尾,然後要選一些之類的...。卡了超久做不出來後,才發現其實它就是一堆線段,然後要選一堆線段,使得同一個位置只能最多被覆蓋到兩次。那其實就直接greedy選右界最靠近左邊的就好了(因為越短,表示你越可以選到後面的)。
這裡寫了個線段樹,來判斷可不可以插入,不過應該可以不用,然後也可以直接$O(N)$的做這個操作XD
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
#define FF first
#define SS second

const int N = 4000 + 5;

class SegTre{
	private:
		struct node{
			int flag=0, val=0;
		} nodes[N<<3];
		int size;
		inline int lc(int x){return 2*x+1;}
		inline int rc(int x){return 2*x+2;}
		inline void push(int l, int r, int id){
			if(r-l > 1){
				nodes[lc(id)].flag+=nodes[id].flag;
				nodes[rc(id)].flag+=nodes[id].flag;
			}
			nodes[id].val += nodes[id].flag;
			nodes[id].flag=0;
		}
		inline void pull(int id){
			nodes[id].val = max(nodes[lc(id)].val+nodes[lc(id)].flag, \
				nodes[rc(id)].val+nodes[rc(id)].flag);
		}
		int query(int ql, int qr, int l, int r, int id){
			if(qr <= l or r <= ql) return 0;
			push(l,r,id);
			if(ql <= l and r <= qr) return nodes[id].val;
			int mid = (l+r)>>1;
			return max(query(ql,qr,l,mid,lc(id)), \
				query(ql,qr,mid,r,rc(id)));
		}
		void modify(int ql, int qr, int l, int r, int v, int id){
			if(qr <= l or r <= ql) return;
			push(l,r,id);
			if(ql <= l and r <= qr){
				nodes[id].flag=v;
				return;
			}
			int mid=(l+r)>>1;
			modify(ql,qr,l,mid,v,lc(id));
			modify(ql,qr,mid,r,v,rc(id));
			pull(id);
		}
	public:
		void build(int* arr, int n){
			size=n;
		}
		int query(int l, int r){
			return query(l, r, 0, size, 0);
		}
		void modify(int l, int r, int v){
			modify(l, r, 0, size, v, 0);
		}
} seg;

int arr[N<<1];
PII pos[N];

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	int n; cin>>n;
	fill(pos,pos+n+1,(PII){-1,-1});
	for(int i=0;i<(n<<1);i++){
		cin>>arr[i];
		if(pos[arr[i]].FF==-1) pos[arr[i]].FF = i;
		else pos[arr[i]].SS = i;
	}
	seg.build(arr, (n<<1) + 3);
	sort(pos+1,pos+n+1,[](PII a, PII b){return a.SS<b.SS;});
	int ans = 0;
	for(int i=1;i<=n;i++){
		if(seg.query(pos[i].FF, pos[i].SS+1) < 2){
			ans++;
			seg.modify(pos[i].FF, pos[i].SS+1, 1);
		}
	}
	cout<<ans<<'\n';
	return 0;
}

留言

這個網誌中的熱門文章

[TIOJ] 1094. C.幼稚國王的獎賞

[IOJ] 19. 啦啦啦

[IOJ] 14. 費氏數列問題