题解:CF421D Bug in Code
fish_love_cat · · 题解
哇去怎么做了一晚上虽然是一边看可塑一边做的()
duel 随到的,结果嫌麻烦毙掉了正解,写出来的双指针 TLE 了 /ng
还好我和 KDL 都读错题了,最后平掉。
简要题意:
给你
WA on #5 警示:支持数看的是鸭鸭数量而不是投票数量,一对放逐鸭同时受到一只鸭的投票,这只鸭的贡献只是
首先我们考虑开桶存每只鸭的吃票数量。
接着对于每个票型的情况开桶做后缀和。
这样我们确认其中一个数字时,合法二元组的数量就可以
具体的,我们将当前票数距离胜诉的数量放到后缀和中查找,所有不小于距离胜诉票数的票型就都可以是合法解。
小心不要越界,同时特判不能一只鸭放逐两次。
如果一只鸭就能胜诉,那么剩下
但这样会算重,刚好把每一个
诶诶好像忘了些什么,不是取并集吗,你这样不是直接将票数简单相加了?
于是对于每一个可能会因为取并集而减少票数的二元组,我们要拎出来再判断一次修改答案。
注意到只有存在一只鸭鸭把当前二元组中的两位全部举报时,才有可能因取并集而少票。
于是根据每一个鸭鸭的举报信息反过来进行判断,我们就可以做到
我偷懒上了个 map,所以是
做完了。
#include<bits/stdc++.h>
#define int long long
#define mk make_pair
using namespace std;
int read(){
int sum=0,fish=1;
char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')fish=-1,c=getchar();
while(c>='0'&&c<='9')sum=sum*10+(c-'0'),c=getchar();
return sum*fish;
}
void print(int x){
if(x<0)putchar('-'),x=-x;
if(x<10)putchar(x+'0');
else print(x/10),putchar(x%10+'0');
}
int a[300005],ans1,ans2;
int b[300005];
map<pair<int,int>,int>mp;
signed main(){
int n=read(),p=read();
for(int i=1;i<=n;i++){
int u=read(),v=read();
a[u]++,a[v]++;
int U=max(u,v);
int V=min(u,v);
mp[mk(U,V)]++;
}
for(int i=1;i<=n;i++)b[a[i]]++;
for(int i=n;i;i--)b[i]+=b[i+1];
for(int i=1;i<=n;i++)
if(a[i]<p)ans1+=b[p-a[i]]-(a[i]*2>=p);
else ans1+=n-1;
ans1>>=1;
for(auto i:mp){
int qwq=a[i.first.first]+a[i.first.second];
ans2-=(qwq-i.second<p&&qwq>=p);
}
print(ans1+ans2);
return 0;
}
/*
时光流转
愿你与珍爱之人
能够再次重逢
*/