补题:对A,B,C序列哈希,同时将A左移 [0,n-1] 位的哈希值作为key、左移位数作为value,将其存入map中,然后枚举B左移 [0,n-1] 位,在map中寻找是否存在哈希值与枚举的B的哈希值-C的哈希值相等,枚举过程中维护答案。复杂度 O ( n l o g n ) O(nlogn) O(nlogn),枚举 O ( n ) O(n) O(n),map存取值 O ( l o g n ) O(logn) O(logn)
如果对于hash不了解可以学习参考我的博客:[哈希传送门]
tips.该代码未交,仅供参考
code
#include
using namespace std;
#define ull unsigned long long
#define maxn 100005
const ull p = 1000000007;
ull a[maxn], b[maxn], c[maxn], B[maxn];
int n, ans = p;
map<ull, int> mp;
void init(int n) {
B[0] = 1;
for (int i = 1; i <= n; i++) B[i] = B[i - 1] * p;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
init(n);
for (int i = 1; i <= n; i++) {
cin >> a[i];
a[i] += a[i - 1] * p;
}
for (int i = 1; i <= n; i++) {
cin >> b[i];
b[i] += b[i - 1] * p;
}
for (int i = 1; i <= n; i++) {
cin >> c[i];
c[i] += c[i - 1] * p;
}
for (int i = 0; i < n; i++) {
ull tmp = (a[n] - a[i] * B[n - i]) * B[i] + a[i];
mp[tmp] = i;
}
for (int i = 0; i < n; i++) {
ull tmp = (b[n] - b[i] * B[n - i]) * B[i] + b[i];
if (mp.count(c[n] - tmp)) {
ans = min(ans, mp[c[n] - tmp] + i);
}
}
if (ans == p)
cout << "-1";
else
cout << ans;
return 0;
}
构造,从叶子节点开始 dfs同时涂色即可保证最多一个ugly node
Accepted code
#include
using namespace std;
#define ll long long
#define bug printf("***********\n");
#define endl "\n"
const ll N = 3e5 + 7;
int n, k;
vector<int> road[N];
int du[N];
bool is[N];
int cnt = 0;
void dfs(int dex) {
cnt++;
printf("%d ", dex);
if (cnt == k) {
return;
}
for (int i = 0; i < road[dex].size(); i++) {
int to = road[dex][i];
if (!is[to]) {
is[dex] = true;
dfs(to);
}
if (cnt == k) {
return;
}
}
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
road[u].push_back(v);
road[v].push_back(u);
du[u]++;
du[v]++;
}
if (n == 1) {
cout << 1 << endl;
return 0;
}
int start = -1;
for (int i = 1; i <= n; i++) {
if (du[i] == 1) {
start = i;
break;
}
}
is[start] = true;
dfs(start);
}
手玩发现,S、T任意串即是答案
Accepted code
#include
using namespace std;
string s1,s2;
int main(){
cin>>s1>>s2;
cout<<s1<<endl;
return 0;
}
四舍五入,要入q至少1.5,同时 1.5 102 {1.5}^{102} 1.5102已经大于1e18。所以当k>102即可输出1.5,k=1和n=1要特判,同时double精度不够,要用long double
Accepted code
#include
using namespace std;
#define db long double
const db eps=1e-7;
db n,x=1;long long k;
bool cmp(db a,db b){
return fabs(a-b)<=eps;
}
bool ck(db q){
x=1;
for(int i=0;i<k;i++){
x*=q;
x=round(x);
}
return (x>n||cmp(x,n));
}
int main(){
scanf("%Lf%lld",&n,&k);
if(k==1){
printf("%.6Lf",n-0.5);
return 0;
}
if(n==1){
printf("0.5");
return 0;
}
if(k>=110){
printf("1.5");
return 0;
}
db l=1.5,r=n-0.5;
while(!cmp(l,r)){
db mid=l+(r-l)*0.5;
if(ck(mid)){
r=mid;
}else{
l=mid;
}
}
printf("%.6Lf",r);
return 0;
}
最后一个脑溢血小错误差两分钟没调出来,不过思路是应该没错,从1到n加点,三个线段树,存区间所有数,区间左端点数,区间右端点数。题中要求倒着删点,我们可以正着加点统计答案再逆序输出。
每次增加两个点i时,答案先增加两个点中间的数字的个数。同时这两个点对答案的贡献是左端点左侧的点中去掉成对点的点数,右端点右侧同理,即代码中的lnum与rnum,三个部分构成该轮答案增加的贡献。复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
如果对线段树不了解可以参考学习我的博文:[线段树传送门]
tips.该代码未交,仅供参考
code
#include
using namespace std;
#define ll long long
#define maxn 300005
#define dl (d << 1)
#define dr (d << 1 | 1)
ll n, a[maxn * 2], idx[maxn][2];
long long sum;
struct node {
ll l, r, sum;
} sgt[maxn << 3], lt[maxn << 3], rt[maxn << 3];
void build(ll d, ll l, ll r) {
sgt[d].l = lt[d].l = rt[d].l = l;
sgt[d].r = lt[d].r = rt[d].r = r;
sgt[d].sum = lt[d].sum = rt[d].sum = 0;
if (l == r) return;
ll mid = l + r >> 1;
build(dl, l, mid);
build(dr, mid + 1, r);
}
void pushup(ll d) { sgt[d].sum = sgt[dl].sum + sgt[dr].sum; }
void pushupl(ll d) { lt[d].sum = lt[dl].sum + lt[dr].sum; }
void pushupr(ll d) { rt[d].sum = rt[dl].sum + rt[dr].sum; }
ll query(ll d, ll l, ll r) {
if (l <= sgt[d].l && sgt[d].r <= r) return sgt[d].sum;
ll mid = sgt[d].l + sgt[d].r >> 1, ret = 0;
if (l <= mid) ret += query(dl, l, r);
if (r > mid) ret += query(dr, l, r);
return ret;
}
ll queryl(ll d, ll l, ll r) {
if (l <= lt[d].l && lt[d].r <= r) return lt[d].sum;
ll mid = lt[d].l + lt[d].r >> 1, ret = 0;
if (l <= mid) ret += queryl(dl, l, r);
if (r > mid) ret += queryl(dr, l, r);
return ret;
}
ll queryr(ll d, ll l, ll r) {
if (l <= rt[d].l && rt[d].r <= r) return rt[d].sum;
ll mid = rt[d].l + rt[d].r >> 1, ret = 0;
if (l <= mid) ret += queryr(dl, l, r);
if (r > mid) ret += queryr(dr, l, r);
return ret;
}
void insert(ll d, ll pos) {
if (sgt[d].l == sgt[d].r) {
++sgt[d].sum;
return;
}
ll mid = sgt[d].l + sgt[d].r >> 1;
if (pos <= mid) insert(dl, pos);
if (mid < pos) insert(dr, pos);
pushup(d);
}
void insertl(ll d, ll pos) {
if (lt[d].l == lt[d].r) {
++lt[d].sum;
return;
}
ll mid = lt[d].l + lt[d].r >> 1;
if (pos <= mid) insertl(dl, pos);
if (mid < pos) insertl(dr, pos);
pushupl(d);
}
void insertr(ll d, ll pos) {
if (rt[d].l == rt[d].r) {
++rt[d].sum;
return;
}
ll mid = rt[d].l + rt[d].r >> 1;
if (pos <= mid) insertr(dl, pos);
if (mid < pos) insertr(dr, pos);
pushupr(d);
}
stack<long long> ans;
int main() {
scanf("%d", &n);
for (ll i = 1, sz = 2 * n; i <= sz; i++) {
scanf("%d", &a[i]);
if (!idx[a[i]][0])
idx[a[i]][0] = i;
else
idx[a[i]][1] = i;
}
build(1, 1, 2 * n);
for (ll i = 1; i <= n; i++) {
ans.push(sum);
sum += query(1, idx[i][0] + 1, idx[i][1] - 1);
ll lnum = query(1, 1, idx[i][0] - 1) - queryl(1, 1, idx[i][0] - 1) * 2;
ll rnum = query(1, idx[i][1] + 1, 2 * n) -
queryr(1, idx[i][1] + 1, 2 * n) * 2;
sum += lnum + rnum;
insert(1, idx[i][0]);
insert(1, idx[i][1]);
insertl(1, idx[i][1]);
insertr(1, idx[i][0]);
}
while (!ans.empty()) {
printf("%lld\n", ans.top());
ans.pop();
}
return 0;
}
模拟题
Accepted code
#include
using namespace std;
const double pi=acos(-1);
void solve(){
double r1,r2,d;
cin>>r1>>r2>>d;
double d2=-(pow(r2*r2*r2-r1*r1*r1+(r1-d)*(r1-d)*(r1-d),1.0/3.0)-r2);
printf("%.10lf\n",d2);
}
int main(){
int t;
cin>>t;
while(t--)solve();
return 0;
}