赞
踩
目录
蓝桥杯ACM训练系统 - C语言网 (dotcpp.com) 以及 题库 - AcWing上可过
本题总分: 5 分【问题描述】求 1 (含)至 20230408 (含)中每个数的和。
本题总分: 5 分【问题描述】两种糖果分别有 9 个和 16 个,要全部分给 7 个小朋友,每个小朋友得到的糖果总数最少为 2 个最多为 5 个,问有多少种不同的分法。只要有其中一个小朋友在两种方案中分到的糖果不完全相同,这两种方案就算作不同的方案
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e2+10;
-
- ll ans=0;
- void dfs(int sum1,int sum2,int cnt)
- {
- if(sum1<0||sum2<0)return;
- if(cnt==7)
- {
- if(sum1==0&&sum2==0)ans++;
- return;
- }
- for(int i=0;i<=sum1;i++)
- {
- for(int j=0;j<=sum2;j++)
- {
- if(i+j>=2&&i+j<=5)
- {
- dfs(sum1-i,sum2-j,cnt+1);
- }
- }
- }
- }
- void solve()
- {
- dfs(9,16,0);
- cout<<ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 10 分【问题描述】小蓝正在玩一款游戏。游戏中魏蜀吴三个国家各自拥有一定数量的士兵X , Y , Z ( 一开始可以认为都为 0 ) 。游戏有 n 个可能会发生的事件,每个事件之间相互独立且最多只会发生一次,当第 i 个事件发生时会分别让 X , Y , Z 增加A i , B i , C i 。当游戏结束时 ( 所有事件的发生与否已经确定 ) ,如果 X , Y , Z 的其中一个大于另外两个之和,我们认为其获胜。例如,当 X > Y + Z 时,我们认为魏国获胜。小蓝想知道游戏结束时如果有其中一个国家获胜,最多发生了多少个事件 ?如果不存在任何能让某国获胜的情况,请输出 − 1 。【输入格式】输入的第一行包含一个整数 n 。第二行包含 n 个整数表示 A i ,相邻整数之间使用一个空格分隔。第三行包含 n 个整数表示 B i ,相邻整数之间使用一个空格分隔。第四行包含 n 个整数表示 C i ,相邻整数之间使用一个空格分隔。【输出格式】输出一行包含一个整数表示答案。【样例输入】31 2 22 3 21 0 7【样例输出】2【样例说明】发生两个事件时,有两种不同的情况会出现获胜方。发生 1 , 2 事件时蜀国获胜。发生 1 , 3 事件时吴国获胜。【评测用例规模与约定】对于 40 % 的评测用例, n ≤ 500 ;对于 70 % 的评测用例, n ≤ 5000 ;对于所有评测用例, 1 ≤ n ≤ 10 5 , 1 ≤ A i , B i , C i ≤ 10 9 。
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e5+10;
-
- struct node
- {
- ll x,y,z;
- };
- bool cmp1(node &a,node &b)
- {
- return a.x-(a.y+a.z)>b.x-(b.y+b.z);
- }
- bool cmp2(node &a,node &b)
- {
- return a.y-(a.x+a.z)>b.y-(b.x+b.z);
- }
- bool cmp3(node &a,node &b)
- {
- return a.z-(a.y+a.x)>b.z-(b.y+b.x);
- }
- int n;
- node a[maxn],b[maxn],c[maxn];
- void solve()
- {
- cin>>n;
- for(int i=1;i<=n;i++)
- {
- cin>>a[i].x;
- b[i].x=c[i].x=a[i].x;
- }
- for(int i=1;i<=n;i++)
- {
- cin>>a[i].y;
- b[i].y=c[i].y=a[i].y;
- }
- for(int i=1;i<=n;i++)
- {
- cin>>a[i].z;
- b[i].z=c[i].z=a[i].z;
- }
- sort(a+1,a+n+1,cmp1);
- sort(b+1,b+n+1,cmp2);
- sort(c+1,c+n+1,cmp3);
- ll ans=-1;
- for(ll i=1,x=0,y=0,z=0;i<=n;i++)
- {
- x+=a[i].x;
- y+=a[i].y;
- z+=a[i].z;
- if(x>y+z)
- {
- ans=max(ans,i);
- }
- }
- for(ll i=1,x=0,y=0,z=0;i<=n;i++)
- {
- x+=b[i].x;
- y+=b[i].y;
- z+=b[i].z;
- if(y>x+z)
- {
- ans=max(ans,i);
- }
- }
- for(ll i=1,x=0,y=0,z=0;i<=n;i++)
- {
- x+=c[i].x;
- y+=c[i].y;
- z+=c[i].z;
- if(z>y+x)
- {
- ans=max(ans,i);
- }
- }
- cout<<ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 10 分【问题描述】有一个长度为 n 的数组(n 是 10 的倍数),每个数 a i 都是区间 [0 , 9] 中的整数。小明发现数组里每种数出现的次数不太平均,而更改第 i 个数的代价为b i ,他想更改若干个数的值使得这 10 种数出现的次数相等(都等于n10),请问代价和最少为多少。【输入格式】输入的第一行包含一个正整数 n 。接下来 n 行,第 i 行包含两个整数 a i , b i ,用一个空格分隔。【输出格式】输出一行包含一个正整数表示答案。【样例输入】101 11 21 32 42 52 63 73 83 94 10【样例输出】27【样例说明】只更改第 1 , 2 , 4 , 5 , 7 , 8 个数,需要花费代价 1 + 2 + 4 + 5 + 7 + 8 = 27 。【评测用例规模与约定】对于 20 % 的评测用例, n ≤ 1000 ;对于所有评测用例, n ≤ 100000 , 0 < b i ≤ 2 × 10 5 。
贪心,按找b从小到大,然后遇到大于n/10的我就把它变成其他数
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e5+10;
-
- struct node
- {
- int a,b;
- bool operator<(const node &o)const
- {
- return b<o.b;
- }
- };
- int n;
- node ai[maxn];
- int cnt[20];
- void solve()
- {
- cin>>n;
- for(int i=1;i<=n;i++)
- {
- cin>>ai[i].a>>ai[i].b;
- cnt[ai[i].a]++;
- }
- sort(ai+1,ai+n+1);
- ll ans=0,f=n/10;
- for(int i=1;i<=n;i++)
- {
- if(cnt[ai[i].a]>f)
- {
- for(int j=0;j<=9;j++)
- {
- if(cnt[j]<f)
- {
- cnt[ai[i].a]--;
- cnt[j]++;
- ans=ans+ai[i].b;
- break;
- }
- }
- }
- }
- cout<<ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 15 分【问题描述】有一个长度为 n 的 01 串,其中有一些位置标记为 ? ,这些位置上可以任意填充 0 或者 1 ,请问如何填充这些位置使得这个 01 串中出现互不重叠的 00 和11 子串最多,输出子串个数。【输入格式】输入一行包含一个字符串。【输出格式】输出一行包含一个整数表示答案。【样例输入】1110?0【样例输出】2【样例说明】如果在问号处填 0 ,则最多出现一个 00 和一个 11 : 111000 。【评测用例规模与约定】对于所有评测用例, 1 ≤ n ≤ 1000000 。
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e6+10;
-
- int n;
- char a[maxn];
- int f[maxn];
- void solve()
- {
- cin>>a+1;
- n=strlen(a+1);
- int ans=0,cnt1=0,cnt0=0;
- for(int i=1;i<=n;i++)
- {
- if(a[i]=='1')
- {
- cnt1++;cnt0=0;
- }else if(a[i]=='0')
- {
- cnt0++;cnt1=0;
- }else if(a[i]=='?')
- {
- if(cnt1==1)
- {
- cnt1++;
- }else if(cnt0==1)
- {
- cnt0++;
- }else
- {
- cnt1++;cnt0++;
- }
- }
- //cout<<cnt1<<" "<<cnt0<<endl;
- if(cnt1==2||cnt0==2)
- {
- ans++;
- cnt1=0;cnt0=0;
- }
- }
- cout<<ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 15 分【问题描述】小蓝拥有 n × n 大小的棋盘,一开始棋盘上全都是白子。小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反 ( 也就是白色棋子变为黑色,黑色棋子变为白色 ) 。请输出所有操作做完后棋盘上每个棋子的颜色。【输入格式】输入的第一行包含两个整数 n , m ,用一个空格分隔,表示棋盘大小与操作数。接下来 m 行每行包含四个整数 x 1 , y 1 , x 2 , y 2 ,相邻整数之间使用一个空格分隔,表示将在 x 1 至 x 2 行和 y 1 至 y 2 列中的棋子颜色取反。【输出格式】输出 n 行,每行 n 个 0 或 1 表示该位置棋子的颜色。如果是白色则输出 0,否则输出 1 。【样例输入】3 31 1 2 22 2 3 31 1 3 3【样例输出】001010100【评测用例规模与约定】对于 30 % 的评测用例, n m ≤ 500 ;对于所有评测用例, 1 ≤ n , m ≤ 2000 , 1 ≤ x 1 ≤ x 2 ≤ n , 1 ≤ y 1 ≤ y 2 ≤ m 。
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=2e3+10;
-
- int n,m;
- int a[maxn][maxn];
- void solve()
- {
- cin>>n>>m;
- for(int i=1,x1,y1,x2,y2;i<=m;i++)
- {
- cin>>x1>>y1>>x2>>y2;
- if(x1>x2)swap(x1,x2);
- if(y1>y2)swap(y1,y2);
- a[x1][y1]++;
- a[x1][y2+1]--;
- a[x2+1][y1]--;
- a[x2+1][y2+1]++;
- }
- for(int i=1;i<=n;i++)
- {
- for(int j=1;j<=n;j++)
- {
- a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
- if(a[i][j]&1)cout<<"1";
- else cout<<"0";
- }
- cout<<endl;
- }
-
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 5.0s内存限制 : 512.0MB本题总分: 20 分【问题描述】给定一个 n × m (n 行 m 列)的矩阵。设一个矩阵的价值为其所有数中的最大值和最小值的乘积。求给定矩阵的所有大小为 a × b (a 行 b 列)的子矩阵的价值的和。答案可能很大,你只需要输出答案对 998244353 取模后的结果。【输入格式】输入的第一行包含四个整数分别表示 n , m , a , b ,相邻整数之间使用一个空格分隔。接下来 n 行每行包含 m 个整数,相邻整数之间使用一个空格分隔,表示矩阵中的每个数 A i , j 。【输出格式】输出一行包含一个整数表示答案。【样例输入】2 3 1 21 2 34 5 6【样例输出】58【样例说明】1 × 2 + 2 × 3 + 4 × 5 + 5 × 6 = 58 。【评测用例规模与约定】对于 40 % 的评测用例, 1 ≤ n , m ≤ 100 ;对于 70 % 的评测用例, 1 ≤ n , m ≤ 500 ;对于所有评测用例, 1 ≤ a ≤ n ≤ 1000 1 ≤ b ≤ m ≤ 1000 1 ≤ A i , j ≤ 10 9 。
单调队列,或者线段树
先维护每个位置前b列的最大最小值,然后再在新矩阵上跑,每个位置前a行的最大最小值,那么不就求的了以每个位置为右下角的a*b的矩阵了嘛
单调队列维护复杂度O(N*N),线段树O(N*N*logN)
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- #define big __int128
- const ll mod=998244353 ;
- const int maxn=1e3+10;
-
- int n,m,x,y;
- ll a[maxn][maxn];
- ll heng[maxn][maxn];
- ll shu[maxn][maxn];
- ll st[maxn],id[maxn];
- int s=0,e=0;
- void solve()
- {
- cin>>n>>m>>x>>y;
- for(int i=1;i<=n;i++)
- {
- for(int j=1;j<=m;j++)
- {
- cin>>a[i][j];
- }
- }
- for(int i=1;i<=n;i++)//维护i,j位置(j-b+1,j)之间最小值
- {
- s=1;e=1;
- st[e]=a[i][1];
- id[e]=1;
- for(int j=1;j<=m;j++)
- {
- while(s<=e&&id[s]<j-y+1)s++;
- while(s<=e&&st[e]>=a[i][j])e--;
- st[++e]=a[i][j];
- id[e]=j;
- heng[i][j]=st[s];
- }
- }
- for(int j=1;j<=m;j++)//维护i,j位置往上a,b矩阵的之间最小值
- {
- s=1;e=1;
- st[e]=heng[1][j];
- id[e]=1;
- for(int i=1;i<=n;i++)
- {
- while(s<=e&&id[s]<i-x+1)s++;
- while(s<=e&&st[e]>=heng[i][j])e--;
- st[++e]=heng[i][j];
- id[e]=i;
- shu[i][j]=st[s];
- }
- }
- for(int i=1;i<=n;i++)//维护i,j位置(j-b+1,j)之间最大值
- {
- s=1;e=1;
- st[e]=a[i][1];
- id[e]=1;
- for(int j=1;j<=m;j++)
- {
- while(s<=e&&id[s]<j-y+1)s++;
- while(s<=e&&st[e]<=a[i][j])e--;
- st[++e]=a[i][j];
- id[e]=j;
- heng[i][j]=st[s];
- }
- }
- ll ans=0;
- for(int j=1;j<=m;j++)//维护i,j位置往上a,b矩阵的之间最大值,并计算答案
- {
- s=1;e=1;
- st[e]=heng[1][j];
- id[e]=1;
- for(int i=1;i<=n;i++)
- {
- while(s<=e&&id[s]<i-x+1)s++;
- while(s<=e&&st[e]<=heng[i][j])e--;
- st[++e]=heng[i][j];
- id[e]=i;
- if(i>=x&&j>=y)ans=(ans+shu[i][j]*st[s]%mod)%mod;
- }
- }
- cout<<ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 20 分【问题描述】给定 n 个正整数 A i ,请找出两个数 i , j 使得 i < j 且 A i 和 A j 存在大于 1 的公因数。如果存在多组 i , j ,请输出 i 最小的那组。如果仍然存在多组 i , j ,请输出 i最小的所有方案中 j 最小的那组。【输入格式】输入的第一行包含一个整数 n 。第二行包含 n 个整数分别表示 A 1 A 2 · · · A n ,相邻整数之间使用一个空格分隔。【输出格式】输出一行包含两个整数分别表示题目要求的 i , j ,用一个空格分隔。【样例输入】55 3 2 6 9【样例输出】2 4【评测用例规模与约定】对于 40 % 的评测用例, n ≤ 5000 ;对于所有评测用例, 1 ≤ n ≤ 10 5 , 1 ≤ A i ≤ 10 6 。
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e6+10;
-
- int n;
- int f[maxn];
- vector<int>v[maxn];
- void solve()
- {
- cin>>n;
- for(int i=1,j;i<=n;i++)
- {
- cin>>j;
- v[j].pd(i);
- }
- for(int i=1;i<=1000000;i++)
- {
- sort(v[i].begin(),v[i].end());
- }
- int l=maxn,r=maxn;
- for(int i=2;i<=1000000;i++)
- {
- if(!f[i])
- {
- vector<int>ans;
- for(auto id:v[i])
- {
- ans.pd(id);
- }
- for(int j=i+i;j<=1000000;j+=i)
- {
- f[j]=1;
- for(auto id:v[j])
- {
- ans.pd(id);
- }
- }
- if(ans.size()>=2)
- {
- sort(ans.begin(),ans.end());
- if(l>ans[0])
- {
- l=ans[0];
- r=ans[1];
- }else if(l==ans[0]&&r>ans[1])
- {
- r=ans[1];
- }
- }
- }
- }
- cout<<l<<" "<<r;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 25 分【问题描述】给定一个含有 n 个元素的数组 A i ,你可以选择两个不相交的子段。求出这两个子段内的数的异或和的差值的最大值。【输入格式】输入的第一行包含一个整数 n 。第二行包含 n 个整数 A i ,相邻整数之间使用一个空格分隔。【输出格式】输出一行包含一个整数表示答案。【样例输入】61 2 4 9 2 7【样例输出】14【样例说明】两个子段可以分别选 1 和 4 , 9 , 2 ,差值为 15 − 1 = 14 。【评测用例规模与约定】对于 40 % 的评测用例, n ≤ 5000 ;对于所有评测用例, 2 ≤ n ≤ 2 × 10 5 , 0 ≤ A i ≤ 2 20 。
01字典树,前缀和
01字典树内存前缀异或的值,然后查询最大最小值,不就得到了以这个位置为末尾的区间最大最小异或值,记得要先加入个0,表示区间不去
后缀异或同理
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=2e5+10;
-
- struct tree01
- {
- int tot;
- int ch[maxn<<5][2];
- void init()
- {
- for(int i=0;i<=tot;i++)ch[i][0]=ch[i][1]=0;
- }
- void add(int x)
- {
- int u=0;
- for(int i=20;i>=0;i--)
- {
- int t=(x>>i)&1;
- if(!ch[u][t])
- {
- ch[u][t]=++tot;
- }
- u=ch[u][t];
- }
- }
- int querymx(int x)
- {
- int u=0;
- int ans=0;
- for(int i=20;i>=0;i--)
- {
- int t=(x>>i)&1;
- if(ch[u][t^1])
- {
- u=ch[u][t^1];
- ans+=(1<<i);
- }else
- {
- u=ch[u][t];
- }
- }
- return ans;
- }
- int querymi(int x)
- {
- int u=0;
- int ans=0;
- for(int i=20;i>=0;i--)
- {
- int t=(x>>i)&1;
- if(ch[u][t])
- {
- u=ch[u][t];
- }else
- {
- u=ch[u][t^1];
- ans+=(1<<i);
- }
- }
- return ans;
- }
- }tree01;
- int n;
- int a[maxn];
- int rmx[maxn],rmi[maxn];//[1,R]区间内的异或最大值最小值
- int lmx[maxn],lmi[maxn];//[L,n]区间内的异或最大值最小值
- void solve()
- {
- cin>>n;
- for(int i=0;i<=n+1;i++)
- {
- rmi[i]=lmi[i]=1e9;
- }
- tree01.tot=0;
- tree01.add(0);//先加个0表示区间不取
- for(int i=1,sum=0;i<=n;i++)
- {
- cin>>a[i];
- sum^=a[i];
- rmx[i]=max(rmx[i-1],tree01.querymx(sum));
- rmi[i]=min(rmi[i-1],tree01.querymi(sum));
- tree01.add(sum);
- //cout<<rmx[i]<<" "<<rmi[i]<<endl;
- }
- tree01.init();
- tree01.tot=0;
- tree01.add(0);//先加个0表示区间不取
- for(int i=n,sum=0;i>=1;i--)
- {
- sum^=a[i];
- lmx[i]=max(lmx[i+1],tree01.querymx(sum));
- lmi[i]=min(lmi[i+1],tree01.querymi(sum));
- tree01.add(sum);
- //cout<<rmx[i]<<" "<<rmi[i]<<endl;
- }
- int ans=0;
- for(int i=1;i<n;i++)
- {
- ans=max(ans,rmx[i]-lmi[i+1]);
- ans=max(ans,lmx[i+1]-rmi[i]);
- // cout<< rmx[i] << " "<< lmi[i+1] <<" "<< lmx[i]<<" "<<rmi[i-1]<<"\n";
- }
- cout<<ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
时间限制 : 3.0s内存限制 : 512.0MB本题总分: 25 分【问题描述】这天,小蓝在二维坐标系的点 ( X , Y ) 上放了一个太阳,看做点光源。他拿来了 n 条线段,将它们平行于 x 轴放置在了坐标系中,第 i 条线段的左端点在 x i , y i ,长度为 l i 。线段之间不会有重合或部分重合的情况(但可能出现端点相交)。小蓝想知道有多少条线段能被太阳照亮(一条线段有长度大于 0的部分被照亮就算)。【输入格式】输入的第一行包含三个正整数 n , X , Y ,相邻整数之间使用一个空格分隔。接下来 n 行,第 i 行包含三个整数 x i , y i , l i ,相邻整数之间使用一个空格分隔。【输出格式】输出一行包含一个正整数表示答案。【样例输入】3 10 20000005 3 56 2 40 1 10【样例输出】2【样例说明】第一条线段在最上面被照亮,第二条线段被第一条完全挡住,第三条线段左边的一段能被照亮。【评测用例规模与约定】对于 30 % 的评测用例, n ≤ 1000 ;对于所有评测用例, 1 ≤ n ≤ 100000 , 0 ≤ x i , X ≤ 10 7 , 0 < y i ≤ 10 5 , 0 < l i ≤100 , 10 6 < Y ≤ 10 7 。
把线段投射到y=0的位置,然后按照y排序,区间覆盖
由于区间端点会是小数,我采用了珂朵莉树
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- #define pii pair<double,double>
- #define It set<ran>::iterator
- const int maxn=1e5+10;
- const double inf=1e15;
-
- struct ran{
- double l, r;
- mutable int v;//mutable 关键字定义一个强制可变量
- bool operator <(const ran &x)const{//运算符重载,用于set的排序
- return l < x.l;//按区间的左端点从小到大来排
- }
- };
- struct ODT
- {
- set<ran>tr;//珂朵莉树的定义
- int ans=0;
-
- It split(double pos)
- {
- It it = tr.lower_bound({pos, -1, 0});//找到所需的pos的迭代器
- if(it != tr.end() && it->l == pos)return it;//看看这个迭代器的l是不是所需要的pos,是的话直接返回就行
- --it;//不是的话就说明肯定是在前一个里面
- double l = it->l;
- double r = it->r;
- int v = it->v;
- tr.erase(it);//我们删掉这个区间
- tr.insert({l, pos - 1, v});//重新塞入两个区间[l, pos -1 ],[pos, r]
- return tr.insert({pos, r, v}).first;//返回以pos开头的区间的迭代器
- }
- void emerge(double l, double r, int x)
- {
- It itr = split(r + 1e-15), itl = split(l);//先找到r+1的迭代器位置,再找l的迭代器位置
-
- //操作
- It it=itl;
- int f=0;
- for(;it!=itr;++it)
- {
- if((it->v)==0)f=1;
- }
- ans+=f;
- //操作
-
- tr.erase(itl, itr);//删掉这一段迭代器
- tr.insert({l, r, x});//重新插入所需区间
- }
-
- }odt;
-
- struct node
- {
- double x1,x2,y;
- bool operator<(const node&o)const
- {
- return y>o.y;
- }
- };
- int n;
- double X,Y;
- node a[maxn];
- double to0(int x,int y)
- {
- if(x==X)return x;
- double k=(Y-y)/(X-x);
- double b=k*X-Y;
- return b/k;
- }
- void solve()
- {
- cin>>n>>X>>Y;
- for(int i=1;i<=n;i++)
- {
- cin>>a[i].x1>>a[i].y>>a[i].x2;
- a[i].x2+=a[i].x1;
- a[i].x1=to0(a[i].x1,a[i].y);
- a[i].x2=to0(a[i].x2,a[i].y);
- }
- sort(a+1,a+n+1);
- //区间覆盖,我选择珂朵莉树
- odt.tr.insert({-inf,inf,0});
- for(int i=1;i<=n;i++)
- {
- odt.emerge(a[i].x1,a[i].x2,1);
- }
- cout<<odt.ans<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。