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);
}
}