codeforces-1163 (div2)
想开div3开成div2了,比赛的时候还以为我又菜了。
赛后经验:关爱视力 从我做起
A.删除第一个点的时候断环成链,不产生贡献,后面每隔一个拆一个点都会让联通块最终答案 + 1
没有可以产生贡献的点的时候就需要删联通块,此时产生反向贡献答案 - 1
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 110; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int main(){ Sca2(N,M); if(!M){ puts("1"); return 0; } N--; M--; int ans = 1; for(int i = 2; i < N ; i += 2){ if(M){ M--; ans++; } } if(M){ if(N % 2 == 0) M--; } ans -= M; Pri(ans); return 0; }
B1 B2. 考虑从左往右不断加入数更新答案
用num[maxn]维护这个数字出现的次数,num2[maxn]维护出现了这个次数的数字有多少
答案的产生有如下三种情况。
1.加入的数a[i]是要被删除的数,那么这个数之前的所有数应当有相同的数目,随手取一个a[i - 1],就有num2[num[a[i - 1]]] * num[a[i - 1]] == i - 1的情况下成立
2.加入的数不是要被删除的数,那么显然如果成立.num[a[i]]将会是前面所有的数字出现的次数,check一下num2[num[a[i]]] * num[a[i]] == i - 1的情况是否成立
3.加入的数不是要被删除的数,且有一种数出现了num[a[i]] + 1次,删除掉这种数的一个数将会满足条件,那么check(num2[num[a[i]]] + 1) * num[a[i]] == i - 1的情况。
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int num[maxn]; int a[maxn]; int num2[maxn]; int vis[maxn]; int main(){ Sca(N); int ans = 1; int cnt = 0; int MAX2 = 0,MAX = 0; for(int i = 1; i <= N ; i ++){ Sca(a[i]); if(!vis[a[i]]){ vis[a[i]] = 1; cnt++; } if(i == 6){ // puts("bug"); } if(num2[num[a[i - 1]]] * num[a[i - 1]] == i - 1){ ans = i; } num2[num[a[i]]]--; num[a[i]]++; num2[num[a[i]]]++; if(num2[num[a[i]]] * num[a[i]] == i - 1){ ans = i; } if(num2[num[a[i]] + 1]){ if((num2[num[a[i]]] + 1) * num[a[i]] == i - 1) ans = i; } } Pri(ans); return 0; }
C1 C2.
思路并不难想,找出所有斜率相同的线,假设有k条斜率相同的线,这k条线对最终产生的贡献将会是k * (所有直线数目 - k )
有问题在于各个直线容易出现重合的情况,需要判重,意识到输出的都是整数,可以用y1 - y2 / x1 - x2的方法求出每条直线的一般式ax + by + c = 0中的a,b,c,除去他们的gcd化为最简情况,直接上map<pair<pair<LL,LL>,LL>,int>比较
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1010; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; map<pair<PLL,LL>,int>Q; map<PLL,int>P; struct Point{ LL x,y; }point[maxn]; int main(){ Sca(N); for(int i = 1; i <= N ; i ++) scanf("%lld%lld",&point[i].x,&point[i].y); int cnt = 0; for(int i = 1; i <= N ; i ++){ for(int j = i + 1; j <= N ; j ++){ LL ka = point[i].y - point[j].y,kb = point[i].x - point[j].x,kc = point[i].y * point[j].x - point[i].x * point[j].y; LL p = __gcd(ka,kb); ka /= p; kb /= p; kc /= p; if(ka < 0 || (!ka && kb < 0)){ ka = -ka; kb = -kb; } if(!Q[mp(mp(ka,kb),kc)]){ Q[mp(mp(ka,kb),kc)] = 1; P[mp(ka,kb)]++; cnt++; } } } LL ans = 0; map<PLL,int>::iterator it; for(it = P.begin(); it != P.end(); it++){ pair<PLL,int> p = *it; ans += (cnt - p.second) * p.second; } Prl(ans / 2); return 0; }