hdu多校5

Posted cjlhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu多校5相关的知识,希望对你有一定的参考价值。

1002

思路:贪心显然不好贪,直接爆搜。

技术分享图片
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int x, k, mx, mn, Mn, Mx;
string s;

void getMx(string &a, int pos, int k, int n) {
    if(mx == Mx) return;
    if(k == 0 || pos == n) {
        int val = 0;
        for(int i = 0; i < n; i++) {
            val *= 10;
            val += a[i] - 0;
        }
        mx = max(mx, val);
        return;
    }
    char val = 0;
    for(int i = n - 1; i > pos; i--) val = max(val, a[i]);
    if(val <= a[pos]) {
        getMx(a, pos + 1, k, n);
    } else {
        for(int i = n - 1; i > pos; i--) {
            if(a[i] == val) {
                swap(a[i], a[pos]);
                getMx(a, pos + 1, k - 1, n);
                swap(a[i], a[pos]);
            }
        }
    }
}

void getMn(string &a, int pos, int k, int n) {
    if(mn == Mn) return;
    if(k == 0 || pos == n) {
        int val = 0;
        for(int i = 0; i < n; i++) {
            val *= 10;
            val += a[i] - 0;
        }
        mn = min(mn, val);
        return;
    }

    if(pos == 0) {
        char val = 9;
        for(int i = n - 1; i > pos; i--) if(a[i] != 0) val = min(val, a[i]);
        if(val >= a[pos]) {
            getMn(a, pos + 1, k, n);
        } else {
            for(int i = n - 1; i > pos; i--) {
                if(a[i] == val) {
                    swap(a[i], a[pos]);
                    getMn(a, pos + 1, k - 1, n);
                    swap(a[i], a[pos]);
                }
            }
        }
    } else {

        char val = 9;
        for(int i = n - 1; i > pos; i--) val = min(val, a[i]);
        if(val >= a[pos]) {
            getMn(a, pos + 1, k, n);
        } else {
            for(int i = n - 1; i > pos; i--) {
                if(a[i] == val) {
                    swap(a[i], a[pos]);
                    getMn(a, pos + 1, k - 1, n);
                    swap(a[i], a[pos]);
                }
            }
        }
    }
}

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        mn = inf;
        mx = -inf;
        Mx = Mn = 0;
        cin >> s >> k;
        string a = s, b = s;
        sort(s.rbegin(), s.rend());
        for(int i = 0; i < s.size(); i++) {
            Mx *= 10;
            Mx += s[i] - 0;
        }
        sort(s.begin(), s.end());

        if(s[0] == 0) {
            for(int i = 1; i < s.size(); i++) {
                if(s[i] != 0) {
                    swap(s[0], s[i]);
                    break;
                }
            }
        }
        for(int i = 0; i < s.size(); i++) {
            Mn *= 10;
            Mn += s[i] - 0;
        }
        getMx(a, 0, k, s.size());
        getMn(b, 0, k, s.size());
        printf("%d %d
", mn, mx);
    }
    return 0;
}


/*
*/
View Code

 

1007

思路:线段树剪剪枝,标程好像是用st表压标记。

技术分享图片
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define ui unsigned int
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define fio ios::sync_with_stdio(false);cin.tie(0)
template<typename T>
inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>
inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const double eps=1e-8;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100000+10,maxn=15000000+10,inf=0x3f3f3f3f;

unsigned int x,y,z;
int n,m;
unsigned int gao()
{
    x=x^(x<<11);
    x=x^(x>>4);
    x=x^(x<<5);
    x=x^(x>>14);
    unsigned int w=x^(y^z);
    x=y;
    y=z;
    z=w;
    return z;
}
ui val[N<<2],lazy[N<<2];
void build(ui l,ui r,int rt)
{
    val[rt]=lazy[rt]=0;
    if(l==r)return ;
    ui m=(l+r)>>1;
    build(ls),build(rs);
}
void update(ui L,ui R,ui c,ui l,ui r,int rt)
{
    if(lazy[rt]>c)return ;
    if(L<=l&&r<=R)
    {
        lazy[rt]=MAX(lazy[rt],c);
        if(lazy[rt]>val[rt])val[rt]=lazy[rt];
        return ;
    }
    ui m=(l+r)>>1;
    if(L<=m)update(L,R,c,ls);
    if(m<R)update(L,R,c,rs);
}
void pushdown(ui l,ui r,int rt)
{
    ui m=(l+r)>>1;
    if(l==m)val[rt<<1]=MAX(val[rt<<1],lazy[rt]);
    if(m+1==r)val[rt<<1|1]=MAX(val[rt<<1|1],lazy[rt]);
    lazy[rt<<1]=MAX(lazy[rt<<1],lazy[rt]);
    lazy[rt<<1|1]=MAX(lazy[rt<<1|1],lazy[rt]);
    lazy[rt]=0;
}
ull ans;
void query(ui l,ui r,int rt)
{
    if(l==r)
    {
        ans^=(1ull*l*val[rt]);
        return ;
    }
    pushdown(l,r,rt);
    ui m=(l+r)>>1;
    query(ls),query(rs);
}
int main()
{
    fio;
    int T;cin>>T;
    while(T--)
    {
        cin>>n>>m>>x>>y>>z;
        build(1,n,1);
        for(int i=0;i<m;i++)
        {
            ui a=gao(),b=gao(),c=gao();
            ui l=MIN(a%n+1,b%n+1),r=MAX(a%n+1,b%n+1),v=c%(1<<30);
            update(l,r,v,1,n,1);
        }
        ans=0;
        query(1,n,1);
        cout<<ans<<"
";
    }
    return 0;
}
/********************

********************/
View Code

 

1005

思路:简单计算几何? 我们队好像写的很麻烦。。。

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1);
struct Point
{
    double x, y;
    Point(double x = 0, double y = 0) :x(x), y(y) {}
};

typedef Point Vector;

Vector operator - (Point A, Point B)
{
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator + (Vector A, Vector B)
{
    return Vector(A.x + B.x, A.y + B.y);
}

Vector operator * (Vector A, double p)
{
    return Vector(A.x * p, A.y * p);
}

Vector operator / (Vector A, double p)
{
    return Vector(A.x / p, A.y / p);
}

double Dot(Vector A,Vector B)
{
    return A.x * B.x + A.y * B.y;
}

double Length(Vector A)
{
    return sqrt(Dot(A,A));
}

double Angle(Vector A,Vector B)  //求角度
{
    return acos(Dot(A,B) / Length(A) / Length(B));
}

double angle(Vector v)
{
    return atan2(v.y,v.x);
}

const double eps = 1e-10;
int dcmp(double x)
{
    if(fabs(x) < eps) return 0;
    else
        return x < 0 ? -1 : 1;
}

bool operator < (const Point& a,const Point& b)
{
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}

bool operator == (const Point& a,const Point &b)
{
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

struct Circle
{
    Point c;
    double r;

    Circle(Point c, double r) :c(c), r(r) {}
    Point point(double a)
    {
        return Point(c.x + cos(a) * r, c.y + sin(a) * r);
    }
};

int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point>& sol)  //求圆和圆的交点
{
    double d = Length(C1.c - C2.c);
    if(dcmp(d) == 0)   //首先圆心要重合
    {
        if(dcmp(C1.r - C2.r) == 0) return -1; //其次半径要相同,然后就可以推出两圆重合
        return 0;
    }
    if(dcmp(C1.r + C2.r - d) < 0) return 0; //相离没交点
    if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0; //圆在圆中,没有交点

    double a = angle(C2.c - C1.c); //向量C1C2的极角
    double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d)); //C1C2到C1P1的角
    Point p1 = C1.point(a-da),p2 = C1.point(a+da);

    sol.push_back(p1);
    if(p1 == p2) return 1; //相切
    sol.push_back(p2);
    return 2; //相交
}

double Pointlen(Point a,Point b){
    double res= sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    return res;
}

double ans;

bool OnCircle(Point x,Circle y){
    double len=(x.x-y.c.x)*(x.x-y.c.x)+(x.y-y.c.y)*(x.y-y.c.y);
    if(len<=y.r*y.r) return true;
    return false;
}

double dot(Point a, Point b) {
    return a.x * b.x + a.y * b.y;
}

int main(){
    int T;scanf("%d",&T);
    while(T--){
        int n;
        double xx;
        scanf("%d%lf",&n,&xx);
        Circle ori((Point){0,0},xx);

        ans=2.0*pi*ori.r;

        for(int i=0;i<n;i++){
            vector<Point> inter;

            double tx,ty,tr;
            scanf("%lf%lf%lf",&tx,&ty,&tr);
            Circle tc((Point){tx,ty},tr);

            int num=getCircleCircleIntersection(ori,tc,inter);

            if(num==0||num==-1) continue;
            else if(num==1){
                if(OnCircle(tc.c,ori))
                    ans+=2.0*tc.r*pi;
            }
            else{

                double plen=Pointlen(inter[1],inter[0])/2.0;


                double slen=2.0*ori.r*asin(plen/ori.r);
                double llen=2.0*pi*ori.r-2.0*ori.r*asin(plen/ori.r);

                Point mid;
                mid.x=(inter[1].x+inter[0].x)/2.0;
                mid.y=(inter[1].y+inter[0].y)/2.0;

                double len1=Pointlen(ori.c,mid);
                double len2=Pointlen(tc.c,ori.c);
                double an1=               2.0*tc.r*asin(plen/tc.r);
                double an2=2.0*pi*tc.r -  2.0*tc.r*asin(plen/tc.r);

                if(dot(mid - ori.c, tc.c - ori.c) >= 0) {
                    if(len1 <= len2) {
                        ans -= min(slen, llen);
                        ans += min(an1, an2);
                    } else {
                        ans -= min(slen, llen);
                        ans += max(an1, an2);
                    }
                } else {
                    ans -= max(slen, llen);
                    ans += min(an1, an2);
                }

            }
        }
        printf("%.12f
",ans);

    }

}
/*
100
1 2.717
-1 0 2.717
*/
View Code

 

补题*********************************************************

1008

思路:感觉这题应该想的出来的,但是比赛确实是没想出来,枚举反转的值,然后去dp。

技术分享图片
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int n, l, r, ans, tot, p1[10], p2[10], dp[N][13], a[N], f[N][13][2];
char s[N];

void solve(int S, int T) {
    tot = 0;
    memset(p1, -1, sizeof(p1));
    memset(p2, -1, sizeof(p2));
    for(int i = 0; i <= S; i++) p1[i] = tot++;
    for(int i = T; i >= S; i--) p2[i] = tot++;
    for(int i = T; i < 10; i++) p1[i] = tot++;
    for(int i = 0; i < tot; i++) dp[0][i] = 0, f[0][i][0] = f[0][i][1] = -1;

    for(int i = 1; i <= n; i++) {
        for(int j = 0; j < tot; j++) {
            dp[i][j] = dp[i - 1][j];
            f[i][j][0] = f[i - 1][j][0];
            f[i][j][1] = f[i - 1][j][1];
            if(j && dp[i][j] < dp[i][j - 1]) {
                dp[i][j] = dp[i][j - 1];
                f[i][j][0] = f[i][j - 1][0];
                f[i][j][1] = f[i][j - 1][1];
            }
            if(p1[a[i]] != -1 && dp[i - 1][p1[a[i]]] + 1 > dp[i][p1[a[i]]]) {
                dp[i][p1[a[i]]] = dp[i - 1][p1[a[i]]] + 1;
                f[i][p1[a[i]]][0] = f[i - 1][p1[a[i]]][0];
                f[i][p1[a[i]]][1] = f[i - 1][p1[a[i]]][1];
            }
            if(p2[a[i]] != -1 && dp[i - 1][p2[a[i]]] + 1 > dp[i][p2[a[i]]]) {
                dp[i][p2[a[i]]] = dp[i - 1][p2[a[i]]] + 1;
                if(f[i][p2[a[i]]][0] == -1) f[i][p2[a[i]]][0] = i;
                f[i][p2[a[i]]][1] = i;
            }
        }
    }
    if(dp[n][tot - 1] > ans) {
        ans = dp[n][tot - 1];
        if(f[n][tot - 1][0] != -1) {
            l = f[n][tot - 1][0];
            r = f[n][tot - 1][1];
        } else {
            l = 1;
            r = 1;
        }
    }
}

int main() {
    int T; scanf("%d", &T);
    while(T--) {
        ans = 0;
        scanf("%d%s", &n, s + 1);
        for(int i = 1; i <= n; i++) a[i] = s[i] - 0;


        for(int i = 0; i < 10; i++) {
            for(int j = i; j < 10; j++) {
                solve(i, j);
            }
        }
        printf("%d %d %d
", ans, l, r);
    }
    return 0;
}


/*
*/
View Code

 

以上是关于hdu多校5的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6090 17多校5 Rikka with Graph(思维简单题)

HDU 6092 17多校5 Rikka with Subset(dp+思维)

2015多校第6场 HDU 5354 Bipartite Graph CDQ,并查集

$HDU 2020$ 多校第一场

hdu 2018 多校 第五场

2017多校Round10(hdu6171~hdu6181)