NOI Online 2020 提高组游记

NOI Online 2020

喂,你们都看到了吧,是 NOI Online 哦

Day1

既然是线上赛就肯定只有Day1的啦

开题,网站卡住;卡了好一会儿,登录...卡住...

开考10分钟后我才看到完整的三道题题面

看T1,没思路;看T2,没思路;看T3,没思路...

然后内心就很崩溃

后来(大概是半小时左右)想到了T2的做法,对于以第i位结尾的逆序对的个数,每次冒泡排序第i位会往前挪一位变成第i-1位,然后逆序对个数同时-1

那这样的话拿个线段树维护一下,如果i>k且逆序对个数>k的,我们就把这个逆序对个数减掉k后算进来就是k轮后的逆序对个数了

然后修改的话逆序对个数只会+1或者-1,随便写写就好了。

总之不难,但是要特判k>=n的情况。我的确特判了,但是出现了下面的让我送命的代码段。

if(k>=n)printf("%lld\n",0);
printf("%lld\n",query(1,1,n,k+1,n)-k*queryb(1,1,n,k+1,n));

没错,少了一个else

你以为这就是结束了吗?

2h时我开始做T1,只需要按照关系2连个边,然后再按关系1连边,看看和能不能变成0就好了。

结果又出现了如下语句。

if(fl)puts("YES\n");
else puts("NO\n");

别问我为什么测样例的时候没注意到,我也不知道为什么...

之后还剩半小时看T3...就随手艹了一个80分的暴力。

你以为我会获得这最后的80分?不,你错了,我重新提交文件的时候,新版的还没有保存,我就把旧版的交上去了。

于是考后的估分原本是100+100+80=280的,被我活生生搞成了0+0+0。

可能OI并不适合我。

Day 12

成绩出来了,T2没有k>=n的数据,我获得了100分。

啊?你问T1和T3?挂了就是挂了呀/kk

代码

T1:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long
int n,m;
struct node{
	int v;
	int nxt;
}edge[200001];
int cnt;
int head[100001];
void add(int a,int c){
	edge[++cnt].v=c;
	edge[cnt].nxt=head[a];
	head[a]=cnt;
}
struct data{
	int id,x,y;
}t[100001];
int f[100001];
int k[100001];
int fa[100001];
int fx,fy;
int tot;
int g;
int s[100001];
int mp[100001];
bool fl,b[100001],r[100001];
bool cmp(data a,data b){
	return a.id>b.id;
}
int father(int a){
	if(fa[a]!=a)fa[a]=father(fa[a]);
	return fa[a];
}
int getfather(int a){
	if(s[a]!=a)s[a]=getfather(s[a]);
	return s[a];
}
int find(int u){
	if(r[u])r[0ll]=1ll;
	b[u]=1ll;
	for(int i=head[u];i;i=edge[i].nxt){
		if(!b[edge[i].v])f[u]=f[u]+find(edge[i].v);
	}
	return k[u]-f[u];
}
void clear(){
	fl=1ll;
	tot=0ll;
	cnt=0ll;
	memset(f,0,sizeof(f));
	memset(k,0,sizeof(k));
	memset(head,0,sizeof(head));
	memset(b,0,sizeof(b));
	memset(r,0,sizeof(r));
	memset(mp,0,sizeof(mp));
}
signed main(){
	int T;
	scanf("%lld",&T);
	while(T){
		clear();
		T--;
		scanf("%lld%lld",&n,&m);
		for(int i=1ll;i<=n;i++){
			scanf("%lld",&f[i]);
		}
		for(int i=1ll;i<=n;i++){
			scanf("%lld",&k[i]);
			fa[i]=i;
		}
		for(int i=1ll;i<=m;i++){
			scanf("%lld%lld%lld",&t[i].id,&t[i].x,&t[i].y);
		}
		sort(t+1ll,t+m+1ll,cmp);
		for(int i=1ll;i<=m;i++){
			if(t[i].id==1)break;
			fx=father(t[i].x);
			fy=father(t[i].y);
			if(fx!=fy){
				fa[fx]=fy;
				f[fy]=f[fy]+f[fx];
				k[fy]=k[fy]+k[fx];
			}
			g=i+1ll;
		}
		for(int i=1ll;i<=n;i++){
			fa[i]=father(i);
			if(fa[i]==i){
				tot++;
				mp[i]=tot;
				s[tot]=tot;
				f[tot]=f[i];
				k[tot]=k[i];
			}
		}
		for(int i=1ll;i<=n;i++)fa[i]=mp[fa[i]];
		for(int i=g;i<=m;i++){
			t[i].x=fa[t[i].x];
			t[i].y=fa[t[i].y];
			if(t[i].x==t[i].y)r[t[i].x]=1ll;
			fx=getfather(t[i].x);
			fy=getfather(t[i].y);
			if(fx!=fy){
				add(t[i].x,t[i].y);
				add(t[i].y,t[i].x);
				s[fx]=fy;
				if(r[fx])r[fy]=1ll;
			}
		}
		for(int i=1ll;i<=tot;i++){
			if(!b[i]){
				r[0ll]=0ll;
				int a=find(i);
				if(r[0ll])a=a%2ll;
				if(a){
					fl=0ll;
					break;
				}
			}
		}
		if(fl)puts("YES");
		else puts("NO");//改过了
	}
}

T2

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int lowbit(int x){return x&-x;}
int bit[200010];
void upd(int x,int val){
	while(x<=n){
		bit[x]+=val;
		x+=lowbit(x);
	}
}
int que(int x){
	int ans=0;
	while(x){
		ans+=bit[x];
		x-=lowbit(x);
	}
	return ans;
}
struct node{
	int pos;
	int val;
}b[200010];
bool operator <(node x,node y){
	return x.val>y.val;
}
int a[200010];
struct nod2{
	int sum;
	int x;
}num[200010];
int t[1000010];
int bbb[1000010];
void update(int o,int l,int r,int x,int val,int type){
	if(x==0)return;
	if(l==r){
		t[o]+=val;
		bbb[o]+=type;
		return;
	}
	int mid=(l+r)/2;
	if(x<=mid)update(o<<1,l,mid,x,val,type);
	else update(o<<1|1,mid+1,r,x,val,type);
	t[o]=t[o<<1]+t[o<<1|1];
	bbb[o]=bbb[o<<1]+bbb[o<<1|1];
}
int query(int o,int l,int r,int L,int R){
	if(L<=l&&r<=R){
		return t[o];
	}
	int ret=0;
	int mid=(l+r)/2;
	if(L<=mid)ret+=query(o<<1,l,mid,L,R);
	if(mid<R)ret+=query(o<<1|1,mid+1,r,L,R);
	return ret;
}
int queryb(int o,int l,int r,int L,int R){
	if(L<=l&&r<=R){
		return bbb[o];
	}
	int ret=0;
	int mid=(l+r)/2;
	if(L<=mid)ret+=queryb(o<<1,l,mid,L,R);
	if(mid<R)ret+=queryb(o<<1|1,mid+1,r,L,R);
	return ret;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%lld",&a[i]);
		b[i].val=a[i],b[i].pos=i;
	}
	sort(b+1,b+1+n);
	for(int i=1;i<=n;++i){
		num[b[i].pos].sum=que(b[i].pos);
		upd(b[i].pos,1);
		num[b[i].pos].x=min(num[b[i].pos].sum,b[i].pos);
		update(1,1,n,num[b[i].pos].x,num[b[i].pos].sum,1);
	}
	for(int i=1;i<=m;++i){
		int opt;
		scanf("%lld",&opt);
		if(opt==1){
			int x;
			scanf("%lld",&x);
			if(a[x]>a[x+1]){
				update(1,1,n,num[x].x,-num[x].sum,-1);
				update(1,1,n,num[x+1].x,-num[x+1].sum,-1);
				swap(num[x],num[x+1]);
				swap(a[x],a[x+1]);
				num[x].sum--;
				num[x].x=min(num[x].sum,x);
				num[x+1].x=min(num[x+1].sum,x+1);
				update(1,1,n,num[x].x,num[x].sum,1);
				update(1,1,n,num[x+1].x,num[x+1].sum,1);
			}
			else if(a[x]==a[x+1])continue;
			else {
				update(1,1,n,num[x].x,-num[x].sum,-1);
				update(1,1,n,num[x+1].x,-num[x+1].sum,-1);
				swap(num[x],num[x+1]);
				swap(a[x],a[x+1]);
				num[x+1].sum++;
				num[x].x=min(num[x].sum,x);
				num[x+1].x=min(num[x+1].sum,x+1);
				update(1,1,n,num[x].x,num[x].sum,1);
				update(1,1,n,num[x+1].x,num[x+1].sum,1);
			}
		}
		else {
			int k;
			scanf("%lld",&k);
			if(k>=n)printf("%lld\n",0);
			else printf("%lld\n",query(1,1,n,k+1,n)-k*queryb(1,1,n,k+1,n));//改过了
		}
	}
} 

T3

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
int n,m;
int dp[200001];
int k,ret,p,s;
int gcd(int a,int b){
	if(a%b==0ll)return b;
	return gcd(b,a%b);
}
void find(int a,int b){
	int l,r;
	l=dp[b];
	r=dp[b];
	while(b>a+1ll){
		b--;
		ret=ret+l*dp[b];
		l=dp[b];
		b--;
		ret=ret+r*dp[b];
		r=dp[b];
	}
	if(b==a+1)ret=ret+(l+r)*dp[a];
	else ret=ret+l*r;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1ll;i<=n;i++)scanf("%lld",&dp[i]);
	sort(dp+1ll,dp+n+1ll);
	for(int i=1ll;i<=m;i++){
		scanf("%lld",&k);
		ret=0ll;
		if(k==0ll){
			for(int j=1ll;j<=n;j++){
				ret=ret+dp[j]*dp[j];
			}
		}else{
			p=gcd(n,k);
			s=n/p;
			for(int j=1ll;j<=n;j=j+s){
				find(j,j+s-1ll);
			}
		}
		printf("%lld\n",ret);
	}
}
posted @ 2020-03-07 16:54  FakeDragon  阅读(597)  评论(0编辑  收藏  举报