自从疫情以来,停止集训,GDKOI也取消了(本蒟蒻去了还是受虐),打比赛的机会也就只有洛谷月赛爆零和水codeforces去了。
还好有这场NOI Online的比赛叫醒了我,让我看到我和其他选手的巨大差距,不然我还在梦游中。
不要问我这等蒟蒻怎么有机会参加NOI Online,我的能力不足以参加。
早上,起床。
打开电脑死都登不上网站。刷了半个小时才登上,心烦意乱。
打开题面。
以下是我当时的思路:
看着T1好可做的样子,拿着一张纸推结论去了。
哇塞,我们可以互减一下,然后让数组结果为零不就是了?真好。我还推到了两种操作的转化公式,操作2一加一减,一加起来和一定?嗯,最后能够消成一个方程组,就推数论去了。
额,方程组的数量不一定啊?那么,在少于系数的时候,我们需要化简成多元不定方程,我们设一个数消掉其中两个变量,不断地消,最后变成原变量数-1组方程,贝祖来判,带回去不断贝祖,这样判到一个通解。
如果多余的话呢?像以前一样解出通解式,然后把多余的带入通解式再看看符不符合就是啦!
嗯,好棒的O(m)思路。
然后我就离正解越来越远了。
T1花了这么多时间???赶紧看看T2。嗯,冒泡有很有意思的性质诶。然后我居然想到了归并(看我很蒟蒻吧),开始思路居然好好的,到最后发现还是处理不了……崩了崩了。
赶紧换用线段树,嗯,写得挺顺利的,只不过能把线段树递归写错而已。
第一个数一定会往后撞对嘛,撞到一个比它大的数就要停下来了对吧,期间碾压过的每个数逆序对减一对吧,然后位置前移对吧。
我:”哇塞线段树区间前移好牛逼的操作,我不会诶。“然后就开始考虑前移相互位置的规律了,额,每个数之间的位置,到自己前面停下来相对于其他数的位置变化,额……
要是谁会区间平移的话,这就是道普及。看来,只有万能平衡树了(幸好自己没敲)。
突然发现离比赛不多了,T3还没做,我……
写了个暴力交了,纯纯的,入门难度的暴力。
然后,网就断了。(我:……)
我好快乐,因为我是七彩橡胶皮球人。
从来没有觉得,自己离咸鸭蛋如此近过。我挂在NOI Online上了。只要是个人写个暴力,分数都比我高,诶。
看看题解,发现T1是个图论而非数论。我恍然大雾了。
额,没什么要说了,自己太菜了,我真的离我的同学,还差得很远。
自己,不够努力。
奉上赛后改正的代码。
#include
#include
#define ll long long
using namespace std;
const int N=1e5+10;
int T, n, m, cnt;
int a[N], b[N], fr[N], to[N], f[N], vis[N];
ll sum[N], sum2[3];
bool solve;
vector<int>v[N];
int getfa(int x) {
return (f[x]==x)?f[x]:(f[x]=getfa(f[x]));
}
bool dfs(int x, int flag) {
vis[x]=flag, sum2[flag]+=sum[x];
bool ok=1;
for (int i = 0; i < v[x].size(); i++) {
int y = v[x][i];
if (vis[y] == vis[x]) ok = 0;
if (!vis[y] && !dfs(y, 3-flag)) ok = 0;
}
return ok;
}
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) scanf("%d", &a[i]);
for(int i=1; i<=n; i++) scanf("%d", &b[i]);
cnt=0, solve=true;
for(int i=1; i<=n; i++) {
f[i]=i;
sum[i]=vis[i]=0;
v[i].clear();
}
for(int i=1; i<=m; i++) {
int flag, x, y;
scanf("%d%d%d", &flag, &x, &y);
if(flag==2) f[getfa(x)]=getfa(y);
else fr[++cnt]=x, to[cnt]=y;
}
for(int i=1; i<=n; i++) {
sum[getfa(i)]+=a[i]-b[i];
}
for(int i=1; i<=cnt; i++) {
int x=getfa(fr[i]), y=getfa(to[i]);
v[x].push_back(y), v[y].push_back(x);
}
for(int i=1; i<=n; i++) {
if(getfa(i)==i&&!vis[i]) {
sum2[1]=sum2[2]=0;
bool ok = dfs(i, 1);
if (ok && sum2[1] != sum2[2]) solve=false;
if (!ok && ((sum2[1] ^ sum2[2]) & 1)) solve=false;
}
}
if(solve) {
puts("YES");
} else {
puts("NO");
}
}
}
#include
#include
#define ll long long
#define lowbits(x) (x&(-x))
using namespace std;
const int N=2e5+10;
int a[N], n, m;
int sum1[N];
void add1(int x, int i) {
if(!x) return;
while(x<=n) {
sum1[x]+=i;
x+=lowbits(x);
}
}
int query1(int x) {
int ans=0;
while(x) {
ans+=sum1[x];
x-=lowbits(x);
}
return ans;
}
int c[N];
ll sum[N];
int cnt[N];
void add(int val, int flag) {
if(!val) return;
int x=val;
while(x<=n) {
sum[x]+=1ll*val*flag;
cnt[x]+=flag;
x+=lowbits(x);
}
}
ll qsum(int x) {
ll ans=0;
while(x) {
ans+=sum[x];
x-=lowbits(x);
}
return ans;
}
int qcnt(int x) {
int ans=0;
while(x) {
ans+=cnt[x];
x-=lowbits(x);
}
return ans;
}
int main() {
scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++) {
scanf("%d", &a[i]);
c[i]=query1(n)-query1(a[i]);
add(c[i], 1);
add1(a[i], 1);
}
while(m--) {
int flag, x;
scanf("%d%d", &flag, &x);
if(flag==1) {
if(a[x]<a[x+1]) {
add(c[x], -1);
add(++c[x],1);
swap(a[x], a[x+1]);
swap(c[x], c[x+1]);
} else {
swap(a[x], a[x+1]);
swap(c[x], c[x+1]);
add(c[x], -1);
add(--c[x],1);
}
} else {
printf("%lld\n", (x>n)?0ll:qsum(n)-qsum(x)-1ll*x*(qcnt(n)-qcnt(x)));
}
}
}
最后,希望我和各位以后都不要重蹈我这次的覆辙,祝愿大家在各自的道路上越走越远。