2020icpc沈阳站K题

该博客介绍了如何计算AUC(Area Under the Curve),它是一种衡量分类器性能的指标。通过排序数据,计算不同阈值下的真正例率(TPR)和假正例率(FPR),并求和矩形面积来得到AUC。文章提供了AC代码实现,并分享了在理解和调试过程中遇到的问题,强调了正确理解TP、TN、FP、FN的重要性。

题目大意:给出nnn个数的分类和预测值,(还有一些概念:TPRTPRTPR,FPRFPRFPR,AUCAUCAUC)求AUCAUCAUC

分析:不难发现最后要求的是若干个矩形的面积,分段求就可以。先给n个数排序然后根据取每个aia_iaiθθθ,若ai−1a_{i-1}ai1+++FNFNFN++,若为−-TNTNTN++。

ac代码:

#include <bits/stdc++.h>

using namespace std;

typedef long double ld;
const int N = 1e6+6;
map<char,vector<int> >mp[4];
struct node{
	char c;ld x;int cnt;int l,r;
	bool operator<(const node&t)const{
		if(x == t.x)return c < t.c;//+,-
		return x < t.x;
	}
}p[N],q[N];
int n;
ld calf(ld fp,ld tn){
//	printf("aaaaaa%.10f\n",1.0*fp/(1.0*tn+1.0*fp));
	return (ld)fp/((ld)tn+(ld)fp);
}
ld calt(ld tp,ld fn){
	return (ld)tp/((ld)tp+(ld)fn);
}
int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 0;i < n;i++){
		char c;ld x;cin >> c >> x;
		p[i].c = c,p[i].x = x;
	}
	sort(p,p+n);ld ans = 0.0;int idx = 0;
	for(int i = 0;i < n;i++){
		if(p[i].x == p[i-1].x)continue;
		node tmp = {'+',p[i].x},tmp1 = {'-',p[i].x};
		p[i].cnt = upper_bound(p,p+n,tmp1) - lower_bound(p,p+n,tmp);
		q[idx] = p[i];q[idx].l = lower_bound(p,p+n,tmp) - p;
		q[idx].r = upper_bound(p,p+n,tmp1) - p;idx++;
		
	}
	ld theta = q[0].x;int tp = 0,fp = 0,tn = 0,fn = 0;
	for(int i = 0;i < n;i++){
		if(p[i].c=='+')tp++;
		else fp++;
	}
//	printf("%d %d %d %d\n",tp,fp,tn,fn);
	ld f = calf((ld)fp,(ld)tn),t = calt((ld)tp,(ld)fn);
//	cout << theta << endl;
//	printf("%.10f %.10f\n",1.0*fp/(1.0*fp+1.0*tn),(ld)tp/((ld)tp+(ld)fn));
//	cout << fixed << setprecision(10) << f <<" "<<t << endl;
	for(int i = 1;i < idx;i++){
		ld theta = q[i].x;int l = q[i-1].l,r = q[i-1].r;
		for(int j = l;j < r;j++)
			if(p[j].c=='+')fn++,tp--;
			else tn++,fp--;
//		if(fp <= 0||tp <= 0)break;
//		cout << theta << endl;
//		cout << fixed << setprecision(10)<<tp<<" "<<fp<<" "<<tn<<" "<<fn<<endl;
		ld f1 = calf((ld)fp,(ld)tn),t1 = calt((ld)tp,(ld)fn);
//		cout << fixed << setprecision(10)<<f1<<" "<<t1<<endl;
		ans = ans+(f-f1)*t1;f = f1;t = t1;
	}
//	ans = ans+t*f;
	cout << fixed << setprecision(12)<<ans << endl;
//	for(int i = 0;i < idx;i++)cout << q[i].c << " " << q[i].x << " "<<q[i].cnt << endl;
	return 0;
}
/*
8
+ 34
+ 33
+ 26
- 34
- 38
+ 39
- 7
- 27

3
+ 2
- 3
- 1

6
+ 7
- 2
- 5
+ 4
- 2
+ 6
*/

p.s. 调了好几个小时人快麻了,问题主要出在TPTPTP,TNTNTN,FPFPFP,FNFNFN的理解上。记得记录ai−1a_{i-1}ai1的个数。时间复杂度OnO_nOn

2020 ICPC沈阳站竞赛有相关的目分析和参赛队伍的复盘情况。 在目方面,有2020/2021 ICPC沈阳站DJourney to Un‘Goro ,该可以通过搜索加剪枝的方法解决,还通过简单思考得出\(XY = \lfloor(n + 1) / 2\rfloor\lceil(n + 1) / 2\rceil\),即\(X\)和\(Y\)各取一半时乘积最大,且\(\vert X - Y\vert\leq1\) 。相关代码如下: ```cpp #include <bits/stdc++.h> #define ll long long #define ull unsigned long long #define endl '\n' #define lowbit(i) (i)&(-i) #define all(x) (x).begin(),(x).end() using namespace std; const ll mod=1e9+7; const double inf=1e18; const double eps=1e-8; ll qpow(ll a,ll b){ ll res=1; while(b){ if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; } return res; } ll getinv(ll a){return qpow(a,mod-2);} ll lcm(ll a,ll b){ return a*b/__gcd(a,b); } ll n,lim,cnt,ans; char s[1000006]; void dfs(ll x,ll cnt0,ll cnt1,bool st){ if(cnt0>lim||cnt1>lim) return; if(x==n){ cout<<s<<endl; if(++cnt>=100) exit(0); return; } s[x]='b'; dfs(x+1,cnt0+(st^1),cnt1+st,st); st^=1; s[x]='r'; dfs(x+1,cnt0+(st^1),cnt1+st,st); } int main(){ //cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); cin>>n; ans=(n+1LL)*(n+1LL)/4; lim=(n+2)/2; cout<<ans<<endl; dfs(0,1,0,0); system("pause"); return 0; } ``` 在参赛队伍复盘方面,有队伍过了五个,获得36th名次,认为被虐得很惨。该队伍回想过的好像都挺简单,不过简单D在考场上没做出来,结束后听人讨论“异或”相关内容就脑补出了解法,同时提到这是失而复得的名额,且三人都好久没做了 [^1][^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值