1. 程式人生 > 其它 >2022.3.26 NOI Online記

2022.3.26 NOI Online記

提高組

T1 丹釣戰

剛開始看到這個題,非常自覺的打了暴力,預計得分 50pts ,後來寫了個主席樹,結果 xixike 學長說主席樹可能會被卡,寫離線樹狀陣列好一些。。。。
但願不會被卡。。。。

#include <algorithm>   
#include <bitset>        
#include <string>        
#include <vector>          
#include <iosfwd>          
#include <cmath>         
#include <complex>        
#include <cstdio>       
#include <cstdlib>       
#include <cstring>       
#include <ctime>         
#include <iostream>     
#include <queue>           
#include <set>              
#define ll long long

using namespace std;
const int maxn = 500000+5;

inline ll read()
{
    ll x=0;
	bool f=1;
	char c=getchar();
	while(c>57||c<48){
	    if(c=='-') f=0; 
		c=getchar();
	}
	while(c<=57&&c>=48)
	    x=(x<<1)+(x<<3)+c-48,c=getchar();
	return f?x:(~x)+1;
}

struct node
{
    int l,r,sum;
}tree[maxn*40];

struct NODE
{
    int a,b,i;
}sz[maxn],sta[maxn];

int n,m,k,t,cnt,tail,num[maxn],b[maxn],rt[maxn];

struct point
{
    int id,w;
}a[maxn];

bool operator < (point s1,point s2)
{
	if(s1.w!=s2.w) return s1.w<s2.w;
	else return s1.id<s2.id;
}

void update(int root)
{
	tree[root].sum=tree[tree[root].l].sum+tree[tree[root].r].sum;
}

void build_0(int &root,int l,int r)
{
	root=++cnt;
	tree[root].l=l;
	tree[root].r=r;
	tree[root].sum=0;
	if(l==r)
		return;
	int mid=(l+r)/2;
	build_0(tree[root].l,l,mid);
	build_0(tree[root].r,mid+1,r);
	update(root);
}

void build(int pre,int &root,int l,int r,int index)
{
	root=++cnt;
	tree[root]=tree[pre];
	
	if(l==r) 
	{
		tree[root].sum++;
		return;
	}
	
	int mid=(l+r)/2;
	if(index<=mid)
	{
		build(tree[pre].l,tree[root].l,l,mid,index);
	}
		
	else
	{
		build(tree[pre].r,tree[root].r,mid+1,r,index);
	}
		
	update(root);
}

int binary(int l,int r,int k)
{ 
	while(l<=r) 
	{
		int mid=(l+r)/2;
		if(a[mid].w>k) 
		{
			r=mid-1;
		}
		
		else 
		{
		    l=mid+1;
		}
	}
	return r;
}

int ask(int root1,int root2,int L,int R,int l,int r)
{
	if(L>R)
	{
		return 0;
	}
	
	if(l>=L&&r<=R)
	{
		return tree[root2].sum-tree[root1].sum;
	}
	
	int mid=(l+r)/2,ans=0;
	
	if(mid>=L)
	{
		ans+=ask(tree[root1].l,tree[root2].l,L,R,l,mid);
	}
		
	if(mid<R)
	{
		ans+=ask(tree[root1].r,tree[root2].r,L,R,mid+1,r);
	}
		
	return ans;
}

int main()
{
	freopen("stack.in", "r", stdin);
	freopen("stack.out", "w", stdout);
	
	n=read(); m=read();cnt=0;
	
	for(int i=1;i<=n;i++) 
	{
		sz[i].a=read();
	}
	   
	for(int i=1;i<=n;i++) 
	{
		sz[i].b=read();
	}
	   
	for(int i=1;i<=n;i++) 
	{
		while(tail&&(sta[tail].a==sz[i].a||sz[i].b>=sta[tail].b)) 
		{
			tail-=1;
		}
		    
		sta[++tail].a=sz[i].a;sta[tail].b=sz[i].b;sta[tail].i=i;
		
		if(tail==1) 
		{
			num[i]=1;
		}
		else 
		{
			num[i]=sta[tail-1].i+1;
		}
		
		a[i].id=i;
		
		a[i].w=num[i];
	} 
	
	sort(a+1,a+n+1);
	
	for(int i=1;i<=n;i++) 
	{
		b[a[i].id]=i;
	}
	
	build_0(rt[0],1,n);
	
	for(int i=1; i<=n; i++)
	{
		build(rt[i-1],rt[i],1,n,b[i]);
	}
		
	int l,r,k;
	
	while(m--) 
	{
		l=read(); r=read();
		k=num[l];
		int index=binary(1,n,k);
		printf("%d\n",ask(rt[l-1],rt[r],1,index,1,n));
	}
	
	return 0;
}

T2 討論

賽時就打了個暴力,是真沒時間了,,,,第一道題我硬生生寫了 3 小時。。。。

#include <bits/stdc++.h>
using namespace std;
const long long A = 1e2 + 7;
const long long B = 1e3 + 7;
const long long C = 1e4 + 7;
const long long D = 1e5 + 7;
const long long E = 1e6 + 7;
const long long INF = 0x3f3f3f3f;
const long long mod = 1e9 + 7;
inline long long read() {
	long long x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
long long t, n;
set<long long> a[C];
bool check(long long x, long long y) {
	bool f1 = false, f2 = false, f3 = false;
	for(long long i = 0; i <= n; i++) {
		if(a[x].find(i) != a[x].end() && a[y].find(i) != a[y].end()) f1 = 1;
		else if(a[x].find(i) != a[x].end() && a[y].find(i) == a[y].end()) f2 = 1;
		else if(a[x].find(i) == a[x].end() && a[y].find(i) != a[y].end()) f3 = 1;
	}
	if(f1 && f2 && f3) return 1;
	return 0;
}
int main() {
	freopen("discuss.in","r",stdin);
    freopen("discuss.out","w",stdout);
	t = read();
	while(t--) {
		long long res = 0, ans1 = 0, ans2 = 0;
		n = read();
		for(long long i = 1; i <= n; i++) {
			long long x = read();
			for(long long j = 1; j <= x; j++) a[i].insert(read());
		}
		for(long long i = 1; i <= n; i++) {
			for(long long j = i +1; j <= n; j++) {
				if(check(i, j)) ans1 = i, ans2 = j, res ++;
			}
		}
		if(!res) puts("NO");
		else printf("YES\n%d %d\n", ans1, ans2);
		for(long long i = 1; i <= n; i++) a[i].clear();
	}
	return 0;
}

T3 如何正確地排序

同上,隨手暴力一波就下了。。。

#include <ctime>         
#include <iostream>     
#include <istream>        
#include <ostream>      
using namespace std;
const long long A = 1e2 + 7;
const long long B = 1e3 + 7;
const long long C = 1e4 + 7;
const long long D = 2e5 + 7;
const long long E = 1e6 + 7;
const long long INF = 0x3f3f3f3f;
const long long mod = 1e9 + 7;
inline long long read(){
	long long x = 0, f = 1; char c = getchar();
	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
long long m, n;
long long a[D][10];
int main(){
	freopen("sort.in","r",stdin);
    freopen("sort.out","w",stdout);
	m=read(),n=read();
	for(long long i = 1; i <= m; i++) {
		for(long long j = 1; j <= n; j++) {
			a[i][j] = read();
		}
	}
	long long ans = 0;
	for(long long i = 1; i <= n; i++) {
		for(long long j = 1; j <= n; j++) {
			long long mn = INF, mx = 0;
			for(long long k = 1; k <= m; k++) {
				mn = min(mn, a[k][i] + a[k][j]);
				mx = max(mx, a[k][i] + a[k][j]);
			}
			ans += mn + mx;
		}
	}
	cout << ans;
	return 0;
}

入門組