Summer training #9

A:树形DP

给出一棵树,但是它的边是有向边,选择一个城市,问最少调整多少条边的方向能使一个选中城市可以到达所有的点,输出最小的调整的边数,和对应的点

要改变的边的权值为1,不需要改变的边的权值为0,

两次dfs 第一次算出以1点为根节点到所有点要改变的边数,第二次以1为根节点向下遍历节点   算出每一个点到达所有点要改变的边数,

dp[son]+=(dp[root]-dp[son])+((tree[i].val)?-1:1),某一点的值是他父节点的值减去他以前的值再考虑他与父节点之间的边的方向。

#include<iostream>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iomanip>
#include<queue>
#include<stack>
using namespace std;
int n,lne;
int dp[200010];
int head[200010];
int city[200010];
struct node
{
    int to,next,val;
}tree[400010];
void add(int a,int b)
{
    tree[lne].to=b;
    tree[lne].val=0;
    tree[lne].next=head[a];
    head[a]=lne++;
    tree[lne].to=a;
    tree[lne].val=1;
    tree[lne].next=head[b];
    head[b]=lne++;
}
void dfs1(int root,int pre)
{
    for(int i=head[root];i!=-1;i=tree[i].next)
    {
        int son=tree[i].to;
        if(son==pre)
        continue;
        dfs1(son,root);
        dp[root]+=dp[son]+tree[i].val;
    }
}
void dfs2(int root,int pre)
{
    for(int i=head[root];i!=-1;i=tree[i].next)
    {
        int son=tree[i].to;
        if(son==pre)
        continue;
        dp[son]+=(dp[root]-dp[son])+((tree[i].val)?-1:1);
        dfs2(son,root);
    }
}
int main()
{
    int a,b;
    while(scanf("%d",&n)!=EOF)
    {
        lne=0;
        memset(head,-1,sizeof(head));
        for(int i=0;i<n-1;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        int k=0,sum=10000000;
        memset(dp,0,sizeof(dp));
        dfs1(1,0);
        dfs2(1,0);
        for(int i=1;i<=n;i++)
        {
            if(dp[i]<sum)
            {
                memset(city,0,sizeof(city));
                k=0;
                city[k++]=i;
                sum=dp[i];
            }
            else if(dp[i]==sum)
            city[k++]=i;
        }
        printf("%d\n",sum);
        for(int i=0;i<k;i++)
        {
            if(i==k-1)
            printf("%d\n",city[i]);
            else printf("%d ",city[i]);
        }
    }
    return 0;
}

B:算表面积 先把每个除了四周都加起来 然后减去四周重复的

#include <bits/stdc++.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#define foror(i,a,b) for(i=a;i<b;i++)
#define foror2(i,a,b) for(i=a;i>b;i--)
#define EPS 1.0e-6
#define PI acos(-1.0)
#define INF 3000000000
#define MOD 1000000009
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
//using ll = long long;
//using ull= unsigned long long;
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que;
typedef long long ll;
int a[110][110];
char s[110][110];
int dir[4][2];
int main()
{
 freopen("input.txt", "r", stdin);
 freopen("output.txt", "w", stdout);
dir[0][0]=-1,dir[0][1]=0;
dir[1][0]=1,dir[1][1]=0;
dir[2][0]=0,dir[2][1]=1;
dir[3][0]=0,dir[3][1]=-1;
 int n,m ;
 cin >> n >> m;
 mem(a,0);
 for(int i=1;i<=n;i++)
        {
        scanf("%s",s[i]+1);
        for(int j=1;j<=m;j++)
        a[i][j]=s[i][j]-‘0‘;
        }
 int ans=0;
 for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
        ans+=a[i][j]*4+2;
        if(a[i][j]==0)
        ans-=2;
        }
 for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
 {
        for(int w=0;w<4;w++)
        {
       int dx=i+dir[w][0];
        int dy=j+dir[w][1];
        ans-=min(a[i][j],a[dx][dy]);
        }
 }
 cout<<ans<<endl;
  return 0;
}

C:DFS+二进制压缩

#include <bits/stdc++.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#define foror(i,a,b) for(i=a;i<b;i++)
#define foror2(i,a,b) for(i=a;i>b;i--)
#define EPS 1.0e-6
#define PI acos(-1.0)
#define INF 3000000000
#define MOD 1000000009
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
//using ll = long long;
//using ull= unsigned long long;
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que;
typedef long long ll;
int ans;
char s[110][110];
int dir[4][2];
int bit[50];
int n,m;
int cal(int n)
{
    int ans=0 ;
    for (ans=0;n;ans++)
    {
        n&=(n-1);
    }
    return ans;
}
void dfs(int row,int pass,int now)
{
 if(row==n)
 {
        int cur=max(pass,cal(now));
        ans=min(ans,cur);
        return ;
 }
 dfs(row+1,pass+1,now);
 dfs(row+1,pass,now|bit[row]);
}
int main()
{
 freopen("input.txt", "r", stdin);
 freopen("output.txt", "w", stdout);
 dir[0][0]=-1,dir[0][1]=0;
 dir[1][0]=1,dir[1][1]=0;
 dir[2][0]=0,dir[2][1]=1;
 dir[3][0]=0,dir[3][1]=-1;
 cin >> n >> m;
 ans=min(n,m);
 for(int i=0;i<n;i++)
 {
        scanf("%s",s[i]);
        for(int j=0;j<m;j++)
        if(s[i][j]==‘*‘)
        bit[i]|=(1<<j);
 }
 dfs(0,0,0);
 cout<<ans<<endl;
  return 0;
}

D:BFS+SG函数 :如果一个点是必胜点 那么他后面和前面的点一定不是必胜点 反之一个点不是必胜点 那么他前面和后面的点 可能是必胜点

while(set.find(x)!=set.end()) x++ 当set为空时 返回1 当set为0-y连续的时 返回的是y+1 当0-y有缺少时 返回的是第一个缺少的数

#include <bits/stdc++.h>
#include <cstring>
#include <iostream>
#include <algorithm>
#define foror(i,a,b) for(i=a;i<b;i++)
#define foror2(i,a,b) for(i=a;i>b;i--)
#define EPS 1.0e-6
#define PI acos(-1.0)
#define INF 3000000000
#define MOD 1000000009
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
//using ll = long long;
//using ull= unsigned long long;
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que;
typedef long long ll;
vector<int> tree[1005];
//vector<int> newtree[1005];
int visit[1005];
int n,m;
int sg[1005];
queue<int> que;
void bfs()
{
 visit[1]=1;
 while(!que.empty())
 {
        int cur=que.front();
        que.pop();
        for(int i=0;i<tree[cur].size();i++)
        {
        if(visit[tree[cur][i]]==0)
        {
        visit[tree[cur][i]]=visit[cur]+1;
        que.push(tree[cur][i]);
        }
        }
 }
}
/*void rebuild()
{
 for(int i=1;i<=n;i++)
 {
        for(int j=0;j<tree[i].size();i++)
        {
        if(visit[tree[i][j]]>visit[i])
        newtree[i].push_back(tree[i][j]);
        }
 }
}*/
int sgdfs(int x)
{
 if(sg[x]!=-1)
 return  sg[x];
 int zero=0;
 //one=-1;
 set<int> a;
 for(int i=0;i<tree[x].size();i++)
 {
        if(visit[tree[x][i]]>visit[x])
        a.insert(sgdfs(tree[x][i]));
 }
 while(a.find(zero)!=a.end())
 zero++;
 sg[x]=zero;
 return sg[x];
}
int main()
{
 freopen("input.txt", "r", stdin);
 freopen("output.txt", "w", stdout);
 mem(sg,-1);
 mem(visit,0);
 cin >> n >> m;
 int s,f;
 for(int i=1;i<=m;i++)
 {
        scanf("%d %d",&s,&f);
        tree[s].push_back(f);
        tree[f].push_back(s);
 }
 que.push(1);
 bfs();
 //rebuild();
 int ans=sgdfs(1);
 if(ans)
 cout<<"Vladimir";
 else
 cout<<"Nikolay";
 //for(int i=1;i<=n;i++)
 //ans=max(ans,visit[i]);
  return 0;
}

F:浮标

因为间距的单调不会使得答案单调,间距过大过小都会使得最后的移动距离不是最优,所以是使用三分而不是二分

对于每次三分,每次在n个点里面假设一个点不动,然后枚举完算一遍,取最优。

while(fabs(r - l) > eps) {
        double mid = (l + r) / 2.0;
        double midd = (mid + r) / 2.0;
        if(cal(mid, 0) > cal(midd, 0)) l = mid;
        else r = midd;
    }
    double ans = cal(l, 0) > cal(r, 0) ? r : l;

三分

#include <bits/stdc++.h>
using namespace std;
#define N 405
const double eps = 1e-12;
double num[N];
int n, id;

double cal(double x, int flag) {
    double res = 0, ans = 100000000;
    for(int st = 1; st <= n; st++) {
        res = 0;
        for(int i = 1; i < st; i++)
            res += fabs(num[st] - (st - i) * x - num[i]);
        for(int i = st + 1; i <= n; i++)
            res += fabs(num[st] + (i - st) * x - num[i]);
        if(ans > res) ans = res, id = st;
    }
    return ans;
}

void solve() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%lf", &num[i]);
    double l = 0, r = 100000000;
    while(fabs(r - l) > eps) {
        double mid = (l + r) / 2.0;
        double midd = (mid + r) / 2.0;
        if(cal(mid, 0) > cal(midd, 0)) l = mid;
        else r = midd;
    }
    double ans = cal(l, 0) > cal(r, 0) ? r : l;
    double res = cal(ans, 1);
    printf("%.4f\n", res);
    for(int i = 1; i < id; i++)
        printf("%.10f ", num[id] - (id - i) * ans);
    printf("%.10f ", num[id]);
    for(int i = id + 1; i <= n; i++)
        printf("%.10f ", num[id] + (i - id) * ans);
}

int main() {
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    solve();
    return 0;
}

G:线段树

I:莫队

K:可持久化并查集

时间: 2024-10-04 20:09:56

Summer training #9的相关文章

Android官方开发文档Training系列课程中文版:手势处理之滚动动画及Scroller

原文地址:http://android.xsoftlab.net/training/gestures/scroll.html 在Android中,滑动经常由ScrollView类来实现.任何超出容器边界的布局都应该将自己内嵌在ScrollView中,以便提供可滚动的视图效果.自定义滚动只有在特定的场景下才会被用到.这节课将会描述这样一种场景:使用scroller显示一种可滚动的效果. 你可以使用Scroller或者OverScroller来收集一些滑动动画所需要的数据.这两个类很相似,但是Ove

2017 UESTC Training for Data Structures

2017 UESTC Training for Data Structures A    水,找区间极差,RMQ怼上去. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i&

WeChall_Training: Programming 1 (Training, Coding)

When you visit this link you receive a message.Submit the same message back to http://www.wechall.net/challenge/training/programming1/index.php?answer=the_messageYour timelimit is 1.337 seconds 解题: 先在浏览器获取自己的cookie,再用python写了个自动提交的程序,header加上自己的cooki

Training的第二十天

今天接着做前天的活,就是实现把下载下来的jpg格式的图片设置为桌面的功能.要实现这个功能的关键点一个是要调用API(SystemParametersInfo)更换桌面:二是要把下载下来的JPG格式的图片转换成Bmp格式的图片才能够应用为桌面. 由于对API没什么概念,所以我从网上查了下资料并从网上copy了有关该API变成C#的代码和把jpg格式的图片转换成bmp格式图片的代码.接着看懂了里面的代码便自己修改了一下.接下来的是完善这个程序和把它加入到windows自动启动的任务中. 对于程序的完

2014 Multi-University Training Contest 6 Apple Tree(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 Apple Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 176    Accepted Submission(s): 120 Problem Description I've bought an orchard an

hdu 4925 Apple Tree--2014 Multi-University Training Contest 6

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 Apple Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 188    Accepted Submission(s): 129 Problem Description I've bought an orchard an

xtu DP Training C.炮兵阵地

炮兵阵地 Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 118564-bit integer IO format: %lld      Java class name: Main 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表

2014 Super Training #1 F Passage 概率DP

原题: HDU 3366   http://acm.hdu.edu.cn/showproblem.php?pid=3366 本来用贪心去做,怎么都WA,后来看网上原来是一个DP题. 首先按P/Q来做排序,即P越大,Q越小就越好,这样可以确保先选最优的路走. dp[i][j]表示已经到了第i条路(说明前i-1条都没成功的情况),还剩j块钱时能够走出去的概率. 则方程: dp[i][j] = way[i].P + way[i].Q*(dp[i+1][j-1]) + way[i].D*(dp[i+1]

2014 UESTC Training for Data Structures H - Cookies Test

H - Cookies Test Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status As chief programmer at a cookie production plant you have many responsibilities, one of them being that the cookies produced and packag

2014 UESTC Training for Data Structures K - 方师傅与栈

K - 方师傅与栈 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Status 方师傅有一个1?N的排列,排列的顺序是固定的,他想要把这个排列重新排列成他喜欢的顺序. 于是他买了一个栈,他会按顺序将排列扔进栈内,在某些时刻将栈顶元素取出,这样出栈后的排列就可以重新排序啦. 例如,原序列是1,2,他先将1入栈,再将2入栈,然后将2出栈,最后将1出栈,那么新序列就变